我想创建一个类,该类的属性可以在内部由其方法__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
答案 0 :(得分:1)
这是属性的用例。没有setter的属性是只读的。在下文中,a
和b
是只读的,而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)