具有只读属性的类

时间:2019-06-11 12:13:05

标签: python python-3.x class attributes

我想创建一个类,该类的属性可以在内部由其方法__setattr__编辑,因此,像self.attr = value这样的尝试将引发AttributeError。这是我到目前为止的内容:

class MyClass():
    def __init__(self, a, b, c):
        self.a, self.b, self.c = a, b, c

    def __repr__(self):
        return '%r class with a=%s, b=%s, c=%s' % (self, self.a, self.b, self.c)

    def __setattr__(self,attr,value):
        raise AttributeError('%r is read-only' % self)

    def setattr_(self,attr,value):
        self.attr = value


>>> obj = MyClass(1,2,3)
>>> obj.setattr_(a,4) # obj.a = 4
AttributeError: 'obj' is read-only # __setattr__ method also applies internally

3 个答案:

答案 0 :(得分:1)

这是属性的用例。没有setter的属性是只读的。在下文中,ab是只读的,而c不是只读的。

class MyClass:
    def __init__(self, a, b, c):
        self._a = a
        self.b = b
        self._c = c

    # a is a read-only property
    @property
    def a(self):
        return self._a

    # b is an ordinary attribute

    # c is a property you can set
    @property
    def c(self):
        return self._c

    @c.setter
    def c(self, value):
        self._c = value

由于您仅为a定义了吸气剂,因此尝试 更改其值将失败。尝试更改b将成功完成。尝试更改c将会成功 如果它是常规属性。

>>> obj = MyClass(1,2,3)
>>> obj.a = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> obj.b = 5
>>> obj.c = 6
>>> obj.c
6

答案 1 :(得分:0)

您可以在Python中使用属性来执行此类任务。首先,通过添加两个下划线将属性设置为“私有”,然后使用@property装饰器创建getter方法:

class MyClass:
    def __init__(self, a, b, c):
        self.__a, self.__b, self.__c = a, b, c

    @property
    def a(self):
        return self.__a

    @property
    def b(self):
        return self.__b

    @property
    def c(self):
        return self.__c

现在,您可以像这样使用您的课程:

>>> my_object = MyClass('foo', 'bar', 'bar')
>>> print(my_object.b)
bar
>>> my_object.b = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

注意

我写了“私人”,因为如果您确实想要,您仍然可以访问它:

>>> my_object._MyClass__b = 42
>>> print(my_object.b)
42

这与Zen of Python有关:“我们都同意这里的成年人”。

答案 2 :(得分:0)

请使用属性。

无论如何,很高兴了解内部原理,这是根据您的问题而工作的代码。只是为了玩。

一旦重新定义__setattr__失败,就无法在该类中设置属性。但是父类中仍然还有一个有效的__setattr__

class MyClass():
    def __init__(self, a, b, c): 
        self.setattr_('a', a)
        self.setattr_('b', b)
        self.setattr_('c', c)

    def __setattr__(self,attr,value):
        raise AttributeError('%r is read-only' % self)

    def setattr_(self,attr,value):
        super().__setattr__(attr, value)

obj = MyClass(1,2,3)
obj.setattr_('a',4)  # note that a is a name (string)