Python property() 高级
一、问题
管理对象的属性。
二、解决方案
定义为property
。
实例:增加对属性的类型检查。
class Person:
def __init__(self, first_name):
self._first_name = first_name
# Getter函数
@property
def first_name(self):
return self._first_name
# Setter函数
@first_name.setter
def first_name(self, value):
if not isinstance(value, str):
raise TypeError('不是字符串。')
self._first_name = value
# Deleter函数
@first_name.deleter
def first_name(self):
raise AttributeError('不能删除。')
a = Person('ke')
print(a.first_name)
输出:
ke
上述三个相关联的方法,名字必须一样。
第一个方法是Getter
函数,使first_name
成为一个属性。
其他两个方法给first_name
属性添加Setter
、Deleter
函数。只有first_name
属性被创建后,后面的装饰器@first_name.setter
、@first_name.deleter
才能被定义。
访问property
时会自动触发getter
、setter
、deleter
方法。
a = Person('ke')
print(a.first_name)
a.first_name = 42
del a.first_name
输出:
ke
TypeError: 不是字符串。
AttributeError: 不能删除。
在Getter
、Setter
函数中,是对_first_name
属性进行操作,这是实际数据保存的地方。
三、讨论
property()
具有fget
、fset
、fdel
属性。
print(Person.first_name.fget)
print(Person.first_name.fset)
print(Person.first_name.fdel)
输出:
<function Person.first_name at 0x0000024E96FA5318>
<function Person.first_name at 0x0000024E99717A68>
<function Person.first_name at 0x0000024E99717AF8>
通常不会直接调用fget
、fset
,会在访问property
时自动触发。
使用property
,将所有访问接口统一起来,对方法的访问也是通过属性访问。
import math
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * self.radius ** 2
@property
def diameter(self):
return self.radius * 2
@property
def perimeter(self):
return 2 * math.pi * self.radius
c = Circle(4)
print(c.radius)
print(c.area)
print(c.perimeter)
输出:
4
50.26548245743669
25.132741228718345
这里对半径、直径、周长、面积的访问都是通过对属性的访问。