怎样让实例中的选定属性变为只读?

8 投票
6 回答
433 浏览
提问于 2025-04-11 09:28

在Python中,我想让一个类的选定实例属性对类外的代码只读。也就是说,外部代码不能直接修改这些属性,唯一的修改方式是通过调用实例的方法。我希望语法能够简洁明了。有什么好的方法吗?(我在下面给出了我目前认为最好的答案…)

6 个回答

2
class C(object):

    def __init__(self):

        self.fullaccess = 0
        self.__readonly = 22 # almost invisible to outside code...

    # define a publicly visible, read-only version of '__readonly':
    readonly = property(lambda self: self.__readonly)

    def inc_readonly( self ):
        self.__readonly += 1

c=C()

# prove regular attribute is RW...
print "c.fullaccess = %s" % c.fullaccess
c.fullaccess = 1234
print "c.fullaccess = %s" % c.fullaccess

# prove 'readonly' is a read-only attribute
print "c.readonly = %s" % c.readonly
try:
    c.readonly = 3
except AttributeError:
    print "Can't change c.readonly"
print "c.readonly = %s" % c.readonly

# change 'readonly' indirectly...
c.inc_readonly()
print "c.readonly = %s" % c.readonly
    @readonly
    self.readonly = 22

这段代码的输出结果是:

$ python ./p.py
c.fullaccess = 0
c.fullaccess = 1234
c.readonly = 22
无法更改 c.readonly
c.readonly = 22
c.readonly = 23

我真想能这样说

也就是说,在一个属性上使用装饰器。这样会显得非常简洁...

2

下面是具体做法:

class whatever(object):
  def __init__(self, a, b, c, ...):
    self.__foobar = 1
    self.__blahblah = 2

  foobar = property(lambda self: self.__foobar)
  blahblah = property(lambda self: self.__blahblah)

(假设 foobarblahblah 是你想要设为只读的属性。)在属性名前加两个下划线,可以有效地把它隐藏起来,这样外部就无法访问到这些内部版本。这个方法只适用于从对象继承的新式类,因为它依赖于 property

不过……这样做其实挺傻的。把变量设为私有似乎是受到了 C++ 和 Java 的影响。你的用户应该通过你设计好的公共接口来使用你的类,而不是因为你强迫他们这样做。

补充:看起来 Kevin 已经发过类似的内容了。

7

你应该使用 @property 装饰器。

>>> class a(object):
...     def __init__(self, x):
...             self.x = x
...     @property
...     def xval(self):
...             return self.x
... 
>>> b = a(5)
>>> b.xval
5
>>> b.xval = 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

撰写回答