gpt4 book ai didi

python - 如何实现@property

转载 作者:太空宇宙 更新时间:2023-11-03 13:57:18 27 4
gpt4 key购买 nike

我正在比较 python 中 @property 的三种略有不同的实现。 Python 文档和“源 1”初始化私有(private)变量 _var_name。此外,源 1 中的代码有一个错误;初始化时它不会访问 .setter 。相比之下,第三个示例正确地初始化了公共(public)变量x

是否有充分的理由在 __init__ 中初始化 _x 来代替 x?它们之间是否还有我未描述的其他差异?

来自 docs :

class C:
def __init__(self):
self._x = None

@property
def x(self):
"""I'm the 'x' property."""
return self._x

@x.setter
def x(self, value):
self._x = value

@x.deleter
def x(self):
del self._x

Source 1 :

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

Source 2 :

class P:

def __init__(self,x):
self.x = x

@property
def x(self):
return self.__x

@x.setter
def x(self, x):
if x < 0:
self.__x = 0
elif x > 1000:
self.__x = 1000
else:
self.__x = x

最佳答案

Is there a good reason to initialize __x or _x in place of x in __init__?

属性通常用于以某种方式转换输入。内部方法(包括__init__)通常已经拥有转换后的数据,并且不希望它再次被转换。例如,考虑这个有点愚蠢但明显的例子:

class C:
# ...
def __init__(self):
f = open(C.default_filename, 'rb')
# ...
self._file = f
@property
def file(self):
return self._file.__name__
@file.setter
def file(self, filename):
self._file = open(f, 'rb')

即使您没有做任何可能错误的事情来传递 setter,内部代码通常都知道类不变量,因此 setter 完成的检查可能会带来额外的开销,但没有任何好处。例如,如果您想要一个将温度设置为 0°C 的方法,则只需设置 self._x = 0 而不是 self.x = 0,因为您知道 0 不需要检查。

另一方面,某些内部方法可能希望以与公众相同的方式查看x。在这种情况下,它应该使用属性而不是底层属性。事实上,您的源 1 是一个完美的示例 - __init__ 只是将其参数直接保存到 _Temperature,允许您构造低于绝对 0 的温度(这很糟糕,因为这实际上是比无限热,CPU 喜欢冷)。在 __init__ 中重复您在 Temperature.setter 中编写的相同前提条件测试是愚蠢的;在这种情况下,只需设置 self.Temperature 即可。

<小时/>

There is additional difference in whether a single or double underscore is used.

单个下划线使属性“按照惯例私有(private)”;双下划线更进一步, mangles the name ,这意味着不会从类代码外部意外访问它。

使用obj._x适用于您的实例; obj.__x 引发 AttributeError。但它只能防止意外访问——如果他们确实想要访问它,他们仍然可以使用obj._C__x。这样做的主要原因是为了防止子类或父类(super class)意外地使用相同的名称。

关于python - 如何实现@property,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49502647/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com