1 动态绑定属性和方法
class student(object):
pass
s = student()
s.name = 'huxiang'#动态绑定一个属性
print s.name
huxiang
动态绑定一个方法
def set_age(self,age):
self.age = age
from types import MethodType
#要利用MethodType来动态绑定方法
s.set_age = MethodType(set_age,s,student)
s.set_age(25)
s.age
25
但是只对这个实例有用,对其他实例不起作用的
s2 = student()
s2.set_age(23)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-7-b8b8d59e5d52> in <module>()
1 s2 = student()
----> 2 s2.set_age(23)
AttributeError: 'student' object has no attribute 'set_age'
可以给整个类class绑定方法:
def set_score(self,score):
self.score = score
student.set_score = MethodType(set_score,None,student)
现在就可以给s2使用set_score方法了
s2.set_score(99)
s2.score
99
2 使用_slots限制class的属性,比如,只允许对Student实例添加name和age属性。
class Student(object):
__slots__ = ('name','age')
s = Student()
s.name = 'Michael'
s.age = 25
只能使用绑定已经申明的那俩个属性,name 和 age,如果在绑定其他属性就报错了,如下:
s.score = 99
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-2329d313a8cb> in <module>()
----> 1 s.score = 99
AttributeError: 'Student' object has no attribute 'score'
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:
class Student(object):
def __init__(self,name,score):
self.name = name
self.score = score
s = Student('huxiang',99)
s.score =8888
print s.score
8888
这样虽然很方便,不用设置专门的函数来设置score的值和显示score的值,但是上面那个8888的分数在实际情况中肯定是不合理的,如果要判断改写的分数是否合理,我们可以设置一个函数set_score来更改,例如:
class Student(object):
def __init__(self,name,score):
self.name = name
self.score = score
def get_score(self):
return self._score
def set_score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s = Student('huxiang',90)
s.set_score(900)#这样就可以给输入设置范围了
s.get_score()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-23-4bab0ecfabe8> in <module>()
1 s = Student('huxiang',90)
----> 2 s.set_score(900)#这样就可以给输入设置范围了
3 s.get_score()
<ipython-input-19-a8231be5f5b0> in set_score(self, value)
10 raise ValueError('score must be an integer!')
11 if value < 0 or value > 100:
---> 12 raise ValueError('score must between 0 ~ 100!')
13 self._score = value
ValueError: score must between 0 ~ 100!
但是还是比较麻烦对不对,还是想直接调用score属性的时候直接可以修改就好了,这里@property就可以排上用场了
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s = Student()
s.score = 68
s.score #不报错
68
s.score = 9999 #可以直接更改,但是超过范围了会报错提示
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-28-c0595552ec14> in <module>()
----> 1 s.score = 9999 #可以直接更改,但是超过范围了会报错提示
<ipython-input-24-92a9cf185e27> in score(self, value)
10 raise ValueError('score must be an integer!')
11 if value < 0 or value > 100:
---> 12 raise ValueError('score must between 0 ~ 100!')
13 self._score = value
ValueError: score must between 0 ~ 100!
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。
3 多重继承
class Animal(object):
pass
# 大类:
class Mammal(Animal):
pass
class Bird(Animal):
pass
# 各种动物:
class Dog(Mammal):
pass
class Bat(Mammal):
pass
class Parrot(Bird):
pass
class Ostrich(Bird):
pass
class Runnable(object):
def run(self):
print('Running...')
class Flyable(object):
def fly(self):
print('Flying...')
class Dog(Mammal, Runnable):#这样Dog就有俩个类的全部属性了
pass
class Bat(Mammal, Flyable):
pass
Mixin
在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为Mixin。
为了更好地看出继承关系,我们把Runnable和Flyable改为RunnableMixin和FlyableMixin。类似的,你还可以定义出肉食动物CarnivorousMixin和植食动物HerbivoresMixin,让某个动物同时拥有好几个Mixin:
小结
由于Python允许使用多重继承,因此,Mixin就是一种常见的设计。
只允许单一继承的语言(如Java)不能使用Mixin的设计。