当我们定义了类class并创建它的实例之后,我们可以给这个实例绑定任何属性和方法,这就是动态语言的灵活性。
我们定义一个class:
>>> class Student(object): pass
给创建的实例绑定属性:
>>> s = Student() >>> s.name = 'Woodman' >>> print(s.name) Woodman
也可以给实例绑定方法:
>>> def set_age(self, age): self.age = age >>> from types import MethodType >>> s.set_age = MethodType(set_age, s) >>> s.set_age(35) >>> s.age 35
需要注意的是,给一个实例绑定的属性和方法对同一个类的其他实例是不起作用的,这个其实也很好理解,如果要给所有实例都绑定属性或方法就需要对class类去绑定。
>>> s2 = Student() >>> s2.set_age(33) Traceback (most recent call last): File "<pyshell#14>", line 1, in <module> s2.set_age(33) AttributeError: 'Student' object has no attribute 'set_age'
给class绑定属性和方法后,其他实例均可调用:
>>> def set_score(self, score): self.score = score >>> Student.set_score = set_score >>> s.set_score(100) >>> s.score 100 >>> s2.set_score(60) >>> s2.score 60
上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。
__slots__
但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
>>> class Student(object): __slots__ = ('name','age') >>> s = Student() >>> s.name = 'Woodman' >>> s.age = 35 >>> s.score = 100 Traceback (most recent call last): File "<pyshell#29>", line 1, in <module> s.score = 100 AttributeError: 'Student' object has no attribute 'score'
可以看到,由于做了slots限制,score这一属性添加不上去,使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用:
>>> class GraduatStudent(Student): pass >>> g = GraduatStudent() >>> g.score = 100
除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。