python @property 用法笔记

https://www.programiz.com/python-programming/property

举个例子:

设计一个类:

class Celsius:
	def __init__(self, temperature = 0):
		self.tmperature = temperature
	
	def to_fahrenheit(self):
		return (self.temperature * 1.8) + 32

用法如下:

man = Celsius()
man.temperature = 37 
man.temperature # output: 37
man.to_fahrenheit # output: 98.60000000000001

当我们为对象属性进行赋值或读取时(如上文的 temperature),Python 会在它的 __dict__ 字典中进行查找:

man.__dict__
# output: {'temperature': 37}

因此 man.temperature 实际上是 man.__dict__['temperature']

现在我要加功能,保证摄氏度不低于 -273 (实际不能低于 -273.15)。

使用 Getters 和 Setters 来对属性进行读取或赋值:

class Celsius:
	def __init__(self, temperature = 0):
		self.set_temperature(temperature)
	def to_fahrenheit(self):
		return (self.get_temperature() * 1.8) + 32
	def get_temperature(self):
		return self._temperature 
	def set_temperature(self):
		if value < -273:
			raise ValueError("Temperature below -273 is not possible")
		self._temperature = value

此时赋值为小于 -273 时则会报错。

然而,对于其他使用这段程序的部分来说,原来他们需要访问的地方都要从 obj.temperature 改成 obj.get_temperature,而赋值的地方 obj.temperature = val 要改成 obj.set_temperature(val) ,这很麻烦。

使用 @property

class Celsius:
	def __init__(self, temperature = 0):
		self.temperature = temperature 
	def to_fahrenheit(self):
		return (self.temperature * 1.8) + 32
	def get_temperature(self):
		print("Getting value")
		return self._temperature
	def set_temperature(self, value):
		if value < -273:
			raise ValueError("Temperature below -273 is not possible")
		print("Setting value")
		self._temperature = value 
	temperature = property(get_temperature, set_temperature) 

最后一行定义了一个 property object temperature,也就是说 property 将一些函数 get_temperature,set_temperature 加到了成员属性访问(temperature)上了。

任意使用到 temperature 的地方会自动调用 get_temperature 而不是 __dict__,任意给 temperature 赋值的地方都会自动调用 set_temperature

则此时:

在这里插入图片描述
会发现在创建一个对象时,会调用 set_temperature,原因是 __init__ 方法里有一句 self.temperature = temperature,这句话自动调用了 set_temperature

通过使用 property,我们可以对下游代码不进行修改而添加上相应的功能。注意此时 temperature 时一个 property object,它为私有变量提供一个接口,真正的值存放在 _temperature 中。

在 Python 中,property() 是一个 built-in function ,它创建并返回一个 property object:

property(fget=None, fset=None, fdef=None, doc=None)

其中 fget,fset,fdel,doc 分别是取值函数、赋值函数、删除属性操作、注释(一个 string)

一个 property object 有三个 methods :getter(),setter(),deleter() ,所以

temperature = property(get_temperature,set_temperature)

相当于:

temperature = property()
temperature = temperature.getter(get_temperature)
temperature = temperature.setter(set_temperature)

进一步,我们使用装饰器来简化代码:

class Celsius:
	def __init__(self, temperature = 0):
		self._temperature = temperature
	def to_fahrenheit(self):
		return self.temperature*1.8 + 32
	@property
	def temperature(self):
		print("Getting value")
		return self._temperature 
	@temperature.setter
	def temperature(self, value):
		if value < -273:
			raise ValueError("Temperature below -273 is not possible")
		print("Setting value")
		self._temperature = value 

假如说只定义 getter 而不定义 setter 的话(没有 @temperature.setter),此时该属性为只读属性

posted @ 2020-04-27 11:24  winechord  阅读(99)  评论(0编辑  收藏  举报