9

@property用来确保对对象实例变量的更改由我需要的方法包装。

当一个实例有一个逻辑上不应该改变的变量时怎么办?例如,如果我正在为 Process 创建一个类,则每个 Process 实例都应该有一个 PID 属性,该属性将经常被访问但不应更改。

处理试图修改该实例变量的人的最 Pythonic 方式是什么?

  • 只是相信用户不要试图改变他们不应该改变的东西吗?

  • 如果实例变量被更改,使用属性但引发异常?

  • 还有什么?

4

4 回答 4

9

在变量名前加上__,并创建只读属性,Python 将处理异常,并且变量本身将受到保护,不会被意外覆盖。

class foo(object):
    def __init__(self, bar):
        self.__bar = bar

    @property
    def bar(self):
        return self.__bar

f = foo('bar')
f.bar         # => bar
f.bar = 'baz' # AttributeError; would have to use f._foo__bar
于 2009-10-06T19:08:31.760 回答
3

简单地信任用户不一定是坏事;如果您只是编写一个快速的 Python 程序,只用一次就扔掉,您很可能只是相信用户不会更改 pid 字段。

恕我直言,强制只读字段的最 Pythonic 方式是使用在尝试设置字段时引发异常的属性。

所以,恕我直言,你对这些东西有很好的直觉。

于 2009-10-06T19:11:39.213 回答
1

也许你可以覆盖__setattr__?在这条线上,

def __setattr__(self, name, value):
    if self.__dict__.has_key(name):
        raise TypeError, 'value is read only'
    self.__dict__[name] = value
于 2009-10-06T19:02:58.803 回答
1

只需使用一个属性和一个隐藏属性(以一个下划线为前缀)。

简单属性是只读的!

>>> class Test (object):
...  @property
...  def bar(self):
...   return self._bar
... 
>>> t = Test()
>>> t._bar = 2
>>> t.bar
2
>>> t.bar = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

用双下划线隐藏不是用来隐藏实现,而是确保你不会与子类的属性发生冲突;以 mixin 为例,它必须非常小心!

如果您只想隐藏属性,请使用单个下划线。如您所见,无需添加额外的魔法——如果您不定义 set 函数,则您的属性与方法的返回值一样是只读的。

于 2009-10-06T22:24:49.260 回答