我已经阅读了很多关于@property
的优点,并且我真的很喜欢它们。作为一个简短的例子
class Foo:
def __init__(self):
self._foo_value = 'foo_value'
@property
def foo_value(self):
return self._foo_value
my_foo = Foo()
print(my_foo.foo_value)
但是,假设我知道我不想做花哨的事情,只想获取Foo.foo_value
的值,我可以用更少的代码实现相同的行为通过忽略@property
,例如
class Foo:
def __init__(self):
self.foo_value = 'foo_value'
my_foo = Foo()
print(my_foo.foo_value)
在这种情况下仍然使用@property
有什么好处吗?
最佳答案
不,property
绝对没有用。这里。 property
的全部是为了避免样板并保持封装。
Pythonic 类定义
假设你写了一个类:class Circle:
def __init__(self, radius):
self.radius = radius
太棒了。现在,有一堆客户端代码,例如:
print(f"The radius is {some_circle.radius}")
非 Python 类定义
但是,假设您希望确保半径永远不会设置为低于 0 的值。哦不!我们应该做什么?像 Java 这样的语言的理念是,您应该首先编写像这样的样板 getter 和 setter:
class Circle:
def __init__(self, radius):
self.set_radius(radius)
def get_radius(self):
return self.radius
def set_radius(self, radius):
self._radius = radius
然后,所有客户端代码都将编写为:
print(f"The radius is {some_circle.get_radius()}")
我们可以修改set_radius
抛出适当的错误:
class Circle:
def __init__(self, radius):
self.set_radius(radius)
def get_radius(self):
return self.radius
def set_radius(self, radius):
if radius < 0:
raise ValueError("Radius must be positive")
self._radius = radius
一开始的所有样板文件都是值得的,因为现在我们可以在不破坏客户端代码的情况下更改控制内部状态访问的方式。
但这不是 Java,这是 Python
在 Python 中,如果以及当我们决定控制访问,我们可以重构我们的类而不会破坏客户端代码!:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, radius):
if radius < 0:
raise ValueError("Radius must be positive")
self._radius = radius
因为说实话。大多数时候,我们宁愿编写像第一个示例那样的类,而不是使用抢占式样板 getter 和 setter 的第二个示例,并且我们喜欢编写如下客户端代码:
pi * circle.radius**2
而不是
pi * circle.get_radius()**2
在 Python 中,我们可以鱼与熊掌兼得。
异常
property
有一个用例就像您的代码中一样:我们希望让我们类的客户端检索一个值,但不设置该值。就像你的例子一样:
>>> class Foo:
... def __init__(self):
... self._foo_value = 'foo_value'
... @property
... def foo_value(self):
... return self._foo_value
...
>>> foo = Foo()
>>> foo.foo_value
'foo_value'
>>> foo.foo_value = 'something else'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
如果上面的行为是您想要的,则 property
实际上是有目的的。当然,这可以很容易地规避,但它确实可以防止“意外”滥用 API。而且,我们仍然可以保持更好看的 foo.foo_value
而不是更丑的foo.get_foo_value()
关于python - @property 的优点假设我只需要获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67657746/