python - @property 的优点假设我只需要获取值

标签 python class properties

我已经阅读了很多关于@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/

相关文章:

python - Django 查询集获取行值作为列名

CSS:如何以任意顺序选择具有所有 4 个类的元素

xml - 在 actionscript 中,检查 xml 节点属性是否存在的最佳方法是什么?

javascript - 找出对象的所有方法

wpf - 从另一个ViewModel引发MVVM属性的最佳方法是什么?

python - 使用 py.test 在类属性上使用 doctest

Python - 我可以访问给我打电话的对象吗?

python - 如何以可读的形式打印此列表?

python - 我如何使用python中的mega api通过共享url列出大型公共(public)文件夹的内容

java - 将 double 型转换为浮点型