常量实例变量?
我使用 @property
来确保对对象实例变量的修改都通过我需要的方法来进行。
那么,当一个实例有一个逻辑上不应该被改变的变量时该怎么办呢?比如说,如果我在创建一个表示进程的类,每个进程实例应该有一个 PID 属性,这个属性经常会被访问,但不应该被修改。
处理有人试图修改这个实例变量的情况,最符合 Python 风格的方法是什么呢?
就简单信任用户,不去改变他们不该改的东西吗?
使用属性,但如果实例变量被修改就抛出一个异常吗?
还有其他方法吗?
4 个回答
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),就需要特别小心!
如果你只是想隐藏这个属性,可以用一个下划线。正如你所看到的,没有什么额外的魔法需要添加——如果你不定义一个设置函数,你的属性就和一个方法的返回值一样,只能读取,不能修改。
3
简单地信任用户并不一定是坏事;如果你只是写一个一次性使用的快速Python程序,那么你可以放心地相信用户不会去改动pid字段。
在我看来,最符合Python风格的做法是使用一个属性,当有人试图修改这个字段时,就抛出一个异常。
所以,我觉得你对这些事情的直觉是很不错的。
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