@yanglt7
2018-12-03T07:28:54.000000Z
字数 2923
阅读 685
Python
class Student(object):def __init__(self, name):self.name = names = Student('Bob')s.score = 90
>>> class Student(object):... name = 'Student'...>>> s = Student() # 创建实例s>>> print(s.name) # 打印 name 属性,因为实例并没有 name 属性,所以会继续查找 class 的 name 属性Student>>> print(Student.name) # 打印类的 name 属性Student>>> s.name = 'Michael' # 给实例绑定 name 属性>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的 name 属性Michael>>> print(Student.name) # 但是类属性并未消失,用 Student.name 仍然可以访问Student>>> del s.name # 如果删除实例的 name 属性>>> print(s.name) # 再次调用 s.name,由于实例的 name 属性没有找到,类的 name 属性就显示出来了Student
class Student(object):pass>>> s = Student()>>> s.name = 'Michael' # 动态给实例绑定一个属性>>> print(s.name)Michael>>> def set_age(self, age): # 定义一个函数作为实例方法... self.age = age...>>> from types import MethodType>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法>>> s.set_age(25) # 调用实例方法>>> s.age # 测试结果25>>> s2 = Student() # 创建新的实例>>> s2.set_age(25) # 尝试调用方法Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'Student' object has no attribute 'set_age'>>> def set_score(self, score):... self.score = score...>>> Student.set_score = set_score>>> s.set_score(100)>>> s.score100>>> s2.set_score(99)>>> s2.score99
限制实例的属性:
class Student(object):__slots__ = ('name', 'age') # 用 tuple 定义允许绑定的属性名称>>> s = Student() # 创建新的实例>>> s.name = 'Michael' # 绑定属性 'name'>>> s.age = 25 # 绑定属性 'age'>>> s.score = 99 # 绑定属性 'score'Traceback (most recent call last):File "<stdin>", line 1, in <module>AttributeError: 'Student' object has no attribute 'score'
使用 __slots__ 要注意,__slots__ 定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:
>>> class GraduateStudent(Student):... pass...>>> g = GraduateStudent()>>> g.score = 9999
除非在子类中也定义 __slots__,这样,子类实例允许定义的属性就是自身的 __slots__ 加上父类的 __slots__。
Python 内置的 @property 装饰器就是负责把一个方法变成属性调用的:
class Student(object):@propertydef score(self):return self._score@score.setterdef 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
把一个 getter 方法变成属性,只需要加上 @property 就可以了,此时,@property 本身又创建了另一个装饰器 @score.setter,负责把一个 setter 方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
>>> s = Student()>>> s.score = 60 # OK,实际转化为s.set_score(60)>>> s.score # OK,实际转化为s.get_score()60>>> s.score = 9999Traceback (most recent call last):...ValueError: score must between 0 ~ 100!
还可以定义只读属性,只定义 getter 方法,不定义 setter 方法就是一个只读属性:
class Student(object):@propertydef birth(self):return self._birth@birth.setterdef birth(self,value):self._birth=value@propertydef age(self):return 2015-self._birth>>> s=Student()>>> s.birth=1998>>> s.birth1998>>> s.age17
利用 @property 给一个 Screen 对象加上 width 和 height 属性,以及一个只读属性 resolution:
>>> class Screen(object):... @property... def width(self):... return self._width... @width.setter... def width(self,value):... self._width=value... @property... def height(self):... return self._height... @height.setter... def height(self,value):... self._height=value... @property... def resolution(self):... return self._width*self._height...>>> s=Screen()>>> s.width=1024>>> s.height=768>>> s.resolution786432