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

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的设计。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值