有没有办法在Python中阻止或改变对类变量的访问,因为可以通过覆盖__setattr__
实例变量?
请注意,this question被标注,实际上是指实例变量,而不是类变量。
基于阅读有关__slots__
的(明显的)死亡陷阱的多篇帖子,我宁愿不去那条路(而且我没有仔细研究过它,知道它是否符合我的要求问)。
示例:
class A(object):
foo = "don't change me"
def __setattr__(self, name, value):
raise ValueError
if __name__ == '__main__':
a1 = A()
print a1.foo # don't change me
print A.foo # don't change me
A.foo = 'bar' # ideally throw an exception or something here
print A.foo # bar
a2 = A()
print a1.foo # bar
print a2.foo # bar
答案 0 :(得分:3)
是的!你完全以同样的方式做到了。
类上的__setattr__
方法控制该类实例的设置属性。在Python中,一切都是对象。对象有类。所以你只需要安排你的类成为某个具有__setattr__
方法的类的实例,就像你想要阻止修改了属性的实例一样!
类的类称为元类。默认元类是type
:“类型类型”或“类类”。您希望创建一个type
的子类,该子类不允许设置其实例属性(正如您创建object
的子类时那样,当您'不允许设置其实例属性时在实例级别执行此操作)。
class CantTouchThis(type):
def __setattr__(cls, attr, value):
raise Exception("NO!")
class SomeClass(object):
__metaclass__ = CantTouchThis
请仔细注意SomeClass
的基类与SomeClass
的类之间的区别。 SomeClass
是object
的子类。它是CantTouchThis
。
几乎所有在实例级别工作的其他东西都可以类似地应用于具有元类的类级别;类就像其他所有类似的实例。由于type
的方法和实现(完全和......等等),它们只有独特的优雅行为。
答案 1 :(得分:0)
你快到了,你只需要将__setattr__
方法移到元类:
class ReadOnlyClass(type):
def __setattr__(self, name, value):
raise ValueError, name
class A(object):
__metaclass__ = ReadOnlyClass
foo = "don't change me"
>>> a1 = A()
>>> a1.foo
"don't change me"
>>> A.foo
"don't change me"
>>> A.foo = 'bar'
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
A.foo = 'bar'
File "<pyshell#4>", line 3, in __setattr__
raise ValueError, name
ValueError: foo
>>> print A.foo
don't change me
>>> a2 = A()
>>> a2.foo
"don't change me"
>>> a2.foo = 'x'
>>> a2.foo
'x'
请注意,尽管元类__setattr__
阻止您更改类中的属性,但它并不会阻止您使用实例属性隐藏它们:如果这是您想要的,那么您需要在两个位置定义__setattr__