7 python 动态绑定,@property的使用__slots_限制class的属性以及多重继承

来源:互联网 发布:铜镀铬和不锈钢 知乎 编辑:程序博客网 时间:2024/06/07 00:15

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 = scorestudent.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 = 99AttributeError: '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 =8888print 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 = valueValueError: 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 = 68s.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 = valueValueError: 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):    passclass Bird(Animal):    pass# 各种动物:class Dog(Mammal):    passclass Bat(Mammal):    passclass Parrot(Bird):    passclass Ostrich(Bird):    pass
class Runnable(object):    def run(self):        print('Running...')class Flyable(object):    def fly(self):        print('Flying...')
class Dog(Mammal, Runnable):#这样Dog就有俩个类的全部属性了    passclass Bat(Mammal, Flyable):    pass

Mixin

在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为Mixin。

为了更好地看出继承关系,我们把Runnable和Flyable改为RunnableMixin和FlyableMixin。类似的,你还可以定义出肉食动物CarnivorousMixin和植食动物HerbivoresMixin,让某个动物同时拥有好几个Mixin:

小结

由于Python允许使用多重继承,因此,Mixin就是一种常见的设计。

只允许单一继承的语言(如Java)不能使用Mixin的设计。

0 0