python通过__slots__限制类实例动态的增加属性、方法
2016-09-04 19:51
796 查看
__slots__实例详解 |
一、python的动态性
>>> class Student(object): ... pass ... >>> s = Student() >>> s.name = 'stemon' >>> print s.name stemon
>>> def set_score(self, score): ... self.score = score ... >>> from types import MethodType >>> s.set_score = MethodType(set_score, s, Student) >>> s.set_score(100) >>> print s.score 100
这里的动态绑定是针对类实例的,给一个实例绑定的属性或者方法,对另一个实例是不起作用的:
>>> s2 = Student() >>> s2.name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'name' >>> s2.set_score(100) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'set_score'
为了给所有的实例都动态绑定该方法,可以给class动态绑定这个方法:
>>> Student.set_score = MethodType(set_score, None, Student) >>> s2.set_score(100) >>> print s2.score 100 >>> s.set_score(99) >>> print s.score 99
通常情况下,类似
set_score这样的方法直接定义在class中,但是这种动态绑定允许我们在程序运行的过程中给class增加功能。
二、__slots__的使用
如果我们想要限制python中class的属性,python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class的实例能添加的属性,比如只能添加name和age两个属性:>>> class Student(object): ... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 ...
然后测试一下:
>>> s.name = 'stemon' >>> s.age = 25 >>> s.score = 99 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'score'
再动态添加一个方法试试:
>>> s.set_score = MethodType(set_score, s, Student) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'set_score'
可见,定义一个__slots__之后,向类实例中添加任何不在__slots__值范围之内的属性或者方法都是不可以的。
三、__slots__的继承性
如果子类没有定义__slots__,那么父类__slots__定义的属性仅对当前类起作用,对继承的子类不起作用。如果子类也定义了__slots__,那么子类允许定义的属性就是自身的__slots__加上父类的__slots__。
再回到Student的定义:
>>> class Student(object): ... __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 ...
不带__slots__的子类的定义:
>>> class GraduateStudent(Student): ... pass ... >>> g = GraduateStudent() >>> g.score = 9999
可以看到,不受父类的__slots__的限制
带__slots__的子类的定义:
>>> class GraduateStudent(Student): ... __slots__ = ('score') ... >>> g = GraduateStudent() >>> g.name = 'stemon' >>> g.age = 26 >>> g.score = 9999 >>> g.height = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'GraduateStudent' object has no attribute 'height'
可见子类如果定义了
ad49
__slots__便会继承父类的__slots__;如果子类没有定义__slots__,便不会受到父类__slots__的限制。
注意一点__slots__限制的仅仅是类的实例的属性或者方法的动态添加,类本身的属性的添加不受__slots__的限制:
>>> GraduateStudent.width = 100 >>> GraduateStudent.height = 100 >>> print g.height 100 >>> print g.width 100
四、__slots__动态添加方法的疑问
补充分析:看下面的一个列子>>> class Student(object): ... __slots__ = ('name', 'age', 'set_score') ... >>> s = Student() >>> s.name = 'stemon' >>> s.age = 25 >>> def set_score(self, score): ... self.score = score ... >>> from types import MethodType >>> s.set_score = MethodType(set_score, s, Student) >>> s.set_score(100) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in set_score AttributeError: 'Student' object has no attribute 'score'
可以看到,如果在__slots__中定义了方法的名字就可以动态添加方法,但是如果该方法中又定义了其他的不在__slots__中的属性,那么会在该方法调用的时候产生异常。
同时注意,__slots__限制的是类的实例的动态属性或者方法的添加,在类的
__init__等方法中定义的属性都是动态的,都受到__slots__的限制。在
__init__等方法的执行过程中,定义的属性跟终端通过实例增加属性是一样的,都是动态的。
在终端通过实例增加方法,受到__slots__的限制,但是在类的声明中通过def实现的方法是不受__slots__限制的,因为在类的声明中实现的方法是静态的。
相关文章推荐
- 【python】详解类class的通过__slots__限制类实例对象的属性(七)
- python 详解类class的通过__slots__限制类实例对象的属性(七)
- Python 动态增加类的属性和方法
- python 通过字符串调用对象属性或方法的实例讲解
- 通过__metaclass__为类动态增加方法实例
- python语言是动态语言、给类添加属性、方法、静态方法和类方法、__slots__()、python中的生成器、yield的用法
- python中为类和实例动态增加方法
- python进阶学习笔记(四)——python中访问限制、创建类属性、定义实例方法、定义类方法、类的继承
- Python实例属性限制(__slots__)
- Python 面向对象编程基础(定义类并创建实例、创建实例属性、初始化实例属性、访问限制、类属性、属性名冲突、实例方法、类方法)
- 7 python 动态绑定,@property的使用__slots_限制class的属性以及多重继承
- Python3学习(23)--__slots__ 限制实例属性的绑定
- python语言是动态语言、给类添加属性、方法、静态方法和类方法、__slots__()、python中的生成器、yield的用法
- Python中的类属性和实例属性以及静态方法和类方法
- Python中动态获取对象的属性和方法的教程
- python动态获取对象的属性和方法
- 动态给实例绑定属性和方法
- Python __slots__限制动态变量个数,节省内存
- textarea不能通过maxlength属性来限制字数的解决方法
- JavaScript中通过prototype属性共享属性和方法的技巧实例