简介
Property,属性访问器,又称特性,是一种让新式类定义自动调用方法来访问或复制实例属性的方式。这种功能与Java和C#语言中的属性(‘getter’和‘setter’)很相似,能动态地计算属性的值而不需要在访问时调用方法。
经典句法
可以通过把一个内置函数的结果赋值给一个类属性来创建一个property,如下所示:
attribute = property(fget,fset,fdel,doc)
使用时给fget传入一个函数用于拦截属性访问,给fset传入一个函数用于属性赋值,给fdel传入一个函数用于属性删除。如果有需要的话,doc参数还可以接收该属性的一个文档字符串。
class Person:
def __init__(self,name):
self._name = name
def getName(self):
print('fetch...')
return self._name
def setName(self,value):
print('change...')
self._name=value
def delName(self):
print('remove...')
del self._name
name = property(getName,setName,delName,"name propety docs")
bob=Person('Bob Smith')
print(bob.name) #调用getName
bob.name='Robert Smith' #调用setName
print(bob.name)
del bob.name #调用delName
print(Person.name.__doc__) #打印文档字符串
运行上述代码,输出如下
fetch...
Bob Smith
change...
fetch...
Robert Smith
remove...
name propety docs
注意:实际数据被存储在_name中,以便不会和property搞混了。
这样,通过属性调用的方式(.号),会隐式地调用property参数中相应的方法。
装饰器形式
内置函数property可以充当一个装饰器,来定义一个函数,并在获取一个属性的时候自动运行该函数
class Person:
@property
def name(self):
pass
回忆一下装饰器的的语法格式,上述代码等价于
class Person:
def name(self):
pass
name=property(name)
我们将第一个例子中的代码稍加改造
class Person:
def __init__(self,name):
self._name = name
@property
def name(self):
"name propety docs" #文档字符串移到此处
print('fetch...')
return self._name
@name.setter
def name(self,value): #函数名同为name
print('change...')
self._name = value
@name.deleter
def name(self): #函数名同为name
print('remove...')
del self._name
bob=Person('Bob Smith')
print(bob.name)
bob.name='Robert Smith'
print(bob.name)
del bob.name
print(Person.name.__doc__)
运行上述代码会得到一样的输出。
和property手动赋值的结果相比,使用装饰器编写只需要3行额外的代码。
说明:
property对象有getter,setter和deleter方法,由于getter组件通常有创建property自身的行为来自动填充,因此可以省略。
总结
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。