由于Python是动态语言,任何实例在运行期都可以动态地添加属性。比如:
class Student(object): def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
此时,Student类有三个属性,name、gender、score,由于是动态语言,在运行时,可以随意添加属性。
student = Student('Bob', 'Male', 99) student.age = 12 # ==> 动态添加年龄age属性
如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。
class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
使用__slots__ = ('name', 'gender', 'score') 限定Student类的属性,这个时候在外部再次添加动态属性age,将会报错。
>>> student = Student('Bob', 'Male', 99) >>> student.age = 12 # ==> 动态添加年龄age属性 Traceback (most recent call last): AttributeError: 'Student' object has no attribute 'age'
__slots__的目的是限制当前类所能拥有的属性,避免因为外部属性的操作导致类属性越来越难以管理。
import types class Person(object): __slots__ = ("name", "age") # 定义__slots__ def __init__(self, newName, newAge): self.name = newName self.age = newAge def eat(self): print("---正在吃---") def run(self): print("---正在跑---") Person.num = 100 # 类Person动态添加类属性num zhangsan = Person("张三", 18) print(zhangsan.name) # 张三 print(zhangsan.age) # 18 print(zhangsan.num) # 100 zhangsan.eat() # ---正在吃--- zhangsan.addr = "北京" # 'Person' object has no attribute 'addr' zhangsan.run = types.MethodType(run, zhangsan) # 'Person' object has no attribute 'run'
通过以上代码可知,__slots__对Person类的动态添加没有限制,而Person类对象zhangsan不能再动态添加对象属性和方法。
对于__slot__有以下几个需要注意的地方:
- __slots__只对类对象进行限制,不对类进行限制
- __slots__不仅限制类对象的属性,还限制类对象的方法
- __slots__仅对当前类起作用,对继承的子类不起作用
- 在子类中定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的__slots__