在学习python属性装饰器时 link ,我偶然发现了以下几行代码:
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)
此代码基本上允许您修改/添加对 Celsius
对象的限制,而无需任何继承 Celsius
类的人重构其代码。
为什么它首先定义一个类变量Temperature
,而不是直接让self.Temperature = property(get_Temperature,Set_Temperature)
然后完成?
编辑:由于评论中存在意见冲突,我现在将代码恢复到原始状态,无论是否有错别字,以方便人们以后阅读。
最佳答案
答案就在 descriptor protocol and attribute lookup order 。如果您这样做:
class Celsius:
def __init__(self, temperature):
self.temperature = property(get_temperature,set_temperature)
self.temperature = temperature
# etc etc
它不会按照您期望的方式运行。完全没有。
t = Celsius(100)
t.temperature = -500 # NO ERROR! BROKEN!
为什么?因为您使用提供给初始值设定项的数字覆盖了属性对象。观察:
get = lambda *args: None # dummy getter
set = lambda *args: None # dummy setter
p = property(get, set) # dummy property
属性应该是Property
的实例:
print(type(p).__name__)
# Property
但是你的温度不再是一种属性:
print(type(t.temperature).__name__)
# int
您用这一行覆盖了它:
self.temperature = temperature
# note that temperature is an int or float
撒上一些print
语句来看看发生了什么:
class Celsius:
def __init__(self, temperature):
self.temperature = property(get_temperature,set_temperature)
print(type(self.temperature).__name__) # Property
self.temperature = temperature
print(type(self.temperature).__name__) # no longer a Property!
# etc etc
因此,属性对象需要存储在类级别,这样它就不会在实例级别被覆盖。当在实例级别访问类级别属性对象时,会自动调用描述符协议(protocol)(Property
是一种描述符;描述符具有不寻常的行为,因此请研究它们小心)。
了解有关类级对象与实例级对象的更多信息 much more detailed answer .
另请注意,需要使用该属性在初始化程序中设置温度。不要不要这样做:
class Celsius:
def __init__(self, temperature):
self._temperature = temperature
使用此代码,您可以在没有错误的情况下执行此操作,但这是不好的:t=Celsius(-500)
。通常,初始化程序应使用该属性来获取或设置私有(private)变量,就像任何其他方法一样:
self.temperature = temperature
现在,正如预期的那样,无效的初始温度将导致错误。
关于python - 为什么在这段代码中先定义类变量,然后再将其转换为实例变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44518852/