前言
我们在了解面向对象的入门知识,知道如何定义一个类和对象的时候,我们应该向它更深的知识进行拓展。
@property 装饰器
它的功能就是将一个隐喻的属性进行包装,该属性是设计者不希望使用者直接访问该属性,这个时候就使用装饰器@property。例如:
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
# getter - 访问器
@property
def age(self):
return self._age
# setter - 修改器
@age.setter
def age(self, age):
self._age = age if 20 < age < 60 else 30
def watch_av(self):
if self._age >= 18:
print('看片')
else:
print('看动漫')
slots魔法
slots可以限定当前的类中的属性的个数,需要注意的是它只能限定该类的对象并不能限定其子类。例如:
class Student(object):
# __slots__魔法的使用
__slots__ = ('_name', '_age')
def __init__(self, name, age):
self._name = name
self._age = age
@property # 属性访问器
def age(self):
return self._age
@age.setter # 属性修改器
def age(self, age):
self._age = age if 15 < age < 25 else 20
def watch_av(self):
if self._age >= 18:
print('看片')
else:
print('看动漫')
静态方法和类方法
所谓的静态方法就是一个方法是属于那一个类而不属于该对象,关键字@staticmethod
,类方法就是对象所拥有的某些行为。
class Tr(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
@property
def a(self):
return self._a
@property
def b(self):
return self._b
@property
def c(self):
return self._c
# 判断是不是三角形
@staticmethod
def is_tr(a, b, c):
return a + b > c and a + c > b and b + c > a
def perimer(self):
return self._a + self._b + self._c
def main():
a = 10
b = 10
c = 12
if Tr.is_tr(a, b, c):
tr = Tr(a, b, c)
print('周长是:%d' % tr.perimer())
if __name__ == '__main__':
main()
和在类中定义静态的方法一样,我们也可以在类中定义类关键字@classmethon
例如:
没有在类中定义类的时候:
import time
class Rectangle:
def __init__(self, width, height):
self._width = width
self._height = height
def perimeter(self):
return (self._width + self._height) * 2
def area(self):
return self._height * self._width
class Clock(object):
local_time = time.localtime()
get_time = list(local_time)
def __init__(self, hour=get_time[3], minute=get_time[4], second=get_time[5]):
# 不要参数 使用系统时间 python中的time模块
self._hour = hour
self._minute = minute
self._second = second
def run(self):
self._second += 1
if self._second == 60:
self._minute += 1
self._second = 0
if self._minute == 60:
self._minute =0
self._hour += 1
if self._hour == 24:
self._hour =0
def show(self):
return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)
# 下面的方法可以获得对象的字符串表示形式
# 当我们用print打印对象时候会自动调用该方法
# def __str__(self):
# return '%02d:%02d:%02d' % (self._hour, self._minute, self._second)
def main():
clock = Clock()
while True:
print(clock.show())
clock.run()
time.sleep(1)
if __name__ == '__main__':
main()
使用了之后:
from time import time, localtime, sleep
class Clock(object):
"""数字时钟"""
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
# 通过类方法创建对象并获取系统时间
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
类之间的关系有如下:
类和类之间的关系有三种:is-a, has-a, use-a
is-a : 简单说就是一个继承关系,比如学生和人类,老鼠和动物。
has-a : 是一种强关联的关系,比如汽车和轮子,4
use-a :是一种依赖关系,比如人撞墙,人使用了墙,否则无墙可撞。
继承和多态
何为继承,就是一个类从另外的一个类中得到该类的属性和方法就称之为继承。得到属性和方法的就叫做子类,提供属性和方法的就叫做父类。子类之中除了父类之中的那些东西之外还可以添加自己需要的方法和属性。当子类继承父类的方法的时候可以重新修改该方法,这就称之为多态
继承:
# 继承-- 从已经有的类创建新类的过程
# 提供继承信息的称为父类(超类/基类)
# 得到继承信息的称为子类(派生类/衍生类)
# 通过继承我们可以将子类中的重复代码抽取到父类中
# 子类通过继承并复用这些代码来减少重复代码的编写
# 将来如果要维护子类的公共代码只需要在父类中进行操作即可
# has - a 关联关系 (人和手)
# use - a 依赖关系 (人和房子)
# is - a 继承关系 (老师和人类,学生和人类)
# 任何时候子类可以替换掉父类
class Person(object):
"""人"""
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
print('%s正在愉快的玩耍.' % self._name)
def watch_av(self):
if self._age >= 18:
print('%s正在观看爱情动作片.' % self._name)
else:
print('%s只能观看《熊出没》.' % self._name)
class Student(Person):
"""学生"""
def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, grade):
self._grade = grade
def study(self, course):
print('%s的%s正在学习%s.' % (self._grade, self._name, course))
class Teacher(Person):
"""老师"""
def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
def teach(self, course):
print('%s%s正在讲%s.' % (self._name, self._title, course))
def main():
stu = Student('王大锤', 15, '初三')
stu.study('数学')
stu.watch_av()
t = Teacher('mr.l', 26, '博士')
t.teach('人体学')
t.watch_av()
if __name__ == '__main__':
main()
多态:
from abc import ABCMeta, abstractmethod
class Pet(object, metaclass=ABCMeta):
"""宠物"""
def __init__(self, nickname):
self._nickname = nickname
@abstractmethod
def make_voice(self):
"""发出声音"""
pass
class Dog(Pet):
"""狗"""
def make_voice(self):
print('%s: 汪汪汪...' % self._nickname)
class Cat(Pet):
"""猫"""
def make_voice(self):
print('%s: 喵...喵...' % self._nickname)
def main():
pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
for pet in pets:
pet.make_voice()
if __name__ == '__main__':
main()
上面代码中的Pet
是一个抽象类,不能直接使用它来创建一个对象,但是可以使用子类来继承它,在子类继承它的时候必须继承该抽象类的抽象方法,
综合案例
1 奥特曼打小怪兽
from random import randint
class Ultraman(object):
__slots__ = ('_name', '_hp', '_mp') # 限定当前这个类里面只有这三个字段
def __init__(self, name, hp, mp):
self._name = name
self._hp = hp
self._mp = mp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp > 0 else 0
@property
def mp(self):
return self._mp
@mp.setter
def mp(self, mp):
self._mp = mp if mp >= 0 else 0
def attack(self, monster):
injury = randint(15, 25)
monster.hp -= injury
def huge_attack(self, monster):
if self._mp >= 50:
self._mp -= 50
injury = monster.hp * 3 // 4
injury = injury if injury >= 50 else 50
monster.hp -= injury
else:
self.attack(monster)
def magic_attack(self, monsters):
if self.mp >= 20:
self.mp -= 20
for monster in monsters:
monster.hp -= randint(10, 15)
def __str__(self):
return '%s奥特曼\n' % self._name + \
'生命值: %d\n' % self._hp + \
'魔法值: %d\n' % self._mp
class Monster(object):
__slots__ = ('_name', '_hp')
def __init__(self, name, hp):
self._name = name
self._hp = hp
@property
def name(self):
return self._name
@property
def hp(self):
return self._hp
@hp.setter
def hp(self, hp):
self._hp = hp if hp >=0 else 0
def attack(self, ultraman):
injury = randint(10, 20)
ultraman.hp -= injury
def __str__(self):
return '%s怪兽\n' % self.name + \
'生命值: %d\n' % self.hp
def main():
u = Ultraman('骆昊', 1000, 500)
print(u)
m1 = Monster('舒玲1', 250)
m2 = Monster('舒玲2', 250)
m3 = Monster('舒玲3', 250)
ms = [m1, m2, m3]
for val in ms:
print(val, end=' ')
attack_round = 1
while u.hp > 0 and (m1.hp + m2.hp + m3.hp) > 0:
print('====第%d回合====' % attack_round)
a = randint(1, 10)
b = randint(0, 2)
if a <= 6:
while ms[b].hp <= 0:
b = randint(0, 2)
u.attack(ms[b])
elif 6 < a <= 9:
u.magic_attack(ms)
else:
u.huge_attack(ms[b])
for index in range(len(ms)):
if ms[index].hp > 0:
ms[index].attack(u)
print(u)
for val in ms:
print(val, end=' ')
attack_round += 1
if u.hp > 0:
print('%s奥 特曼胜利' % u.name)
else:
print('小怪兽获胜')
if __name__ == '__main__':
main()
2 Puke
from random import randrange
class Card(object):
"""一张牌"""
def __init__(self, suite, face):
self._suite = suite
self._face = face
@property
def face(self):
return self._face
@property
def suite(self):
return self._suite
def __str__(self):
if self._face == 1:
face_str = 'A'
elif self._face == 11:
face_str = 'J'
elif self._face == 12:
face_str = 'Q'
elif self._face == 13:
face_str = 'K'
else:
face_str = str(self._face)
return '%s%s' % (self._suite, face_str)
class Poker(object):
"""一副牌"""
def __init__(self):
self._cards = []
self._current = 0
for suite in '♠♥♦♣':
for face in range(1, 14):
card = Card(suite, face)
self._cards.append(card)
@property
def cards(self):
return self._cards
def shuffle(self):
"""洗牌"""
self._current = 0
cards_len = len(self._cards)
for index in range(cards_len):
pos = randrange(cards_len)
self._cards[index], self.cards[pos] = \
self._cards[pos], self.cards[index]
# 使用属性一般需要返回一个值
@property
def next(self):
"""发牌"""
card = self.cards[self._current]
self._current += 1
return card
@property
def has_next(self):
"""还有没有牌"""
return self._current < len(self._cards)
class Player(object):
def __init__(self, name):
self._name = name
self._cards_on_hand = []
@property
def name(self):
return self._name
@property
def cards_on_hand(self):
return self._cards_on_hand
# 得到卡片
def get(self, card):
self._cards_on_hand.append(card)
# 排序
def arrange(self):
self._cards_on_hand.sort(key=get_key)
# 点数计数
@property
def count(self):
total = 0
for val in self._cards_on_hand:
total += val.face
return total
def get_key(card):
return card.face
def main():
p = Poker()
p.shuffle()
user = Player('ljl')
com1 = Player('c1')
while p.has_next:
print()
print('玩家:%d-------电脑:%d' % (user.count, com1.count))
if user.count > 0:
for i in user.cards_on_hand:
print(i, end='')
print('-------------', end='')
for i in com1.cards_on_hand:
print(i, end='')
f = input('是否还要继续游戏y or n:')
if f == 'y':
user.get(p.next)
if user.count > 21:
print('%d玩家输了' % user.count)
return False
if com1.count < 15:
com1.get(p.next)
if com1.count > 21:
print('玩家胜利')
return False
if __name__ == '__main__':
main()