天天看点

Python新式类工具之property

简介

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广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。