class Student():
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return 'Student(name={0}, age={1})'.format(self.name, self.age);
s = Student('jack', 20)
print(s)
try:
s.sex = 'boy' ## 由于__slots__的约束, Student对象不能有除name, age之外的属性,
except Exception as e:
print(e)
# Student2继承自 Student 没有定义__slots__, 因此可以动态绑定任意属性
class Student2(Student):
def __init__(self,name, age):
self.name = name
self.age = age
s2 = Student2('bob', 22)
print(s2)
s2.sex = 'boy'
print('s2.name = ', s2.name)
print('s2.age = ', s2.age)
print('s2.sex = ', s2.sex)
# Student3继承自Student, 且定义了__slots__, 因此将继承父类的__slots__
class Student3(Student):
__slots__ = ()
def __init__(self, name, age):
self.name = name
self.age = age
s3 = Student3('jack', 23)
print(s3)
try:
s3.sex = 'boy' # Student3继承了Student的__slots__, 因此也只能定义 name 和 age属性
print('s2.name = ', s2.name)
print('s2.age = ', s2.age)
print('s2.sex = ', s2.sex)
except Exception as e:
print(e)
# 给上述 s2 对象绑定 set_sex() 方法
from types import MethodType
def set_sex(self, sex):
self.sex = sex
print('s2.sex = ', s2.sex)
s2.set_sex = MethodType(set_sex, s2)
s2.set_sex('girl')
print('s2.sex = ', s2.sex)
st1 = Student2('zhangsan', 18)
try:
st1.set_sex('boy') # set_sex() 只绑定到了s2对象上, 其他对象没有这个方法
except Exception as e:
print(e)
# 给 Student2 类绑定 set_sex()方法
Student2.set_sex = set_sex # 注意不要加括号 (), 否则是在调用函数
st2 = Student2('lisi', 20)
try:
print('st2.sex = ', st2.sex)
except Exception as e:
print(e)
st2.set_sex('boy')
print('st2.sex = ', st2.sex)
@property 装饰器可以使得方法可以像属性一样使用, 这点跟C#中的属性如出一辙
class Student4():
def __init__(self, name, birth):
self.name = name
self.birth = birth
self.__score = 0
# score 装饰成为可读可写属性
@property
def score(self):
return self.__score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be integer')
if not 0 <= value <= 100 :
raise ValueError('score must between 0 and 100')
self.__score = value
# 定义 age 属性, 该属性为只读属性
@property
def age(self):
return 2018 - self.birth
jack = Student4('jack', 2000)
print('jack.birth = ', jack.birth)
print('jack.age = ', jack.age)
jack.birth = 2002
print('jack.age = ', jack.age) # 通过属性读取 age
print('jack.score = ', jack.score) # 通过属性读取 score
jack.score = 50 # 通过属性修改 score
print('jack.score = ', jack.score)
try:
jack.score = 150
except Exception as e:
print(e)
print('jack.score = ', jack.score)
python支持多重继承, 但多重继承容易使继承体系很快变得十分复杂, 采用MixIn的设计原则, 可以避免这个问题. 主要思路就是每个类只继承自一条主干, 而通过继承自其它的MixIn类来增加功能和实现代码复用. MixIn类类似与java中的interface,java中使用interface来设计接口, python中使用MixIn这种类来设计接口.
class RunnableMixIn():
def run(self):
print(self.name, 'is running...')
class FlyableMixIn():
def fly(self):
print(self.name, 'is flying...')
class Animal():
def __init__(self, name):
self.name = name
class Bird(Animal):
pass
class Mammal(Animal):
pass
class Dog(Mammal, RunnableMixIn):
pass
class Bat(Mammal, FlyableMixIn):
pass
dog = Dog('hasky') # Dog类继承了 RunnableMixIn, 所以有run()方法
dog.run()
bat = Bat('bat man') # Bat类继承了 FlyableMixIn, 所以有fly()方法
bat.fly()