是否可以覆盖类的__setattr__?

时间:2014-06-15 21:48:41

标签: python

在Python中,我知道可以说像

这样的东西
>>> class C:
...   def __setattr__(self, name, value):
...     print("Hey, you can't set {0} to {1}!".format(name, value))
...
>>> x = C()
>>> x.y = 5
Hey, you can't set y to 5!

但以下情况仍有效:

>>> C.y = 5
>>> print(C.y)
5

是否可以获得如下功能:

>>> C.y = 5
Hey, you can't set y to 5!

完全出于好奇,因为我无法想到一个真正实用的例子。

1 个答案:

答案 0 :(得分:9)

像所有特殊方法一样,__setattr__ is accessed on the type;对于类的实例,对于类,即元类

您必须在自定义元类上定义它,而不是直接在类本身上定义它:

class SetAttrMeta(type):
    def __setattr__(cls, name, value):
        print("Hey, you can't set {0} to {1}!".format(name, value))

class C(metaclass=SetAttrMeta):
    pass
然后,Python会在__setattr__的返回值上查找type(C),此处为SetAttrMeta

演示:

>>> class SetAttrMeta(type):
...     def __setattr__(cls, name, value):
...         print("Hey, you can't set {0} to {1}!".format(name, value))
... 
>>> class C(metaclass=SetAttrMeta):
...     pass
... 
>>> C.spam = 'eggs'
Hey, you can't set spam to eggs!