Brandon
Brandon

Reputation: 1605

Is it possible to override __setattr__ for a class?

In Python, I know it's possible to say something like

>>> 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!

But the following still works:

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

Is it possible to get functionality like:

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

Asking solely out of curiosity, as I can't really think of an example where that'd be genuinely practical.

Upvotes: 5

Views: 1416

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121894

Like all special methods, __setattr__ is accessed on the type; for instances that is the class, for classes, that is the metaclass.

You'll have to define it on a custom metaclass instead of directly on the class itself:

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 then looks up __setattr__ on the return value of type(C), which here is SetAttrMeta.

Demo:

>>> 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!

Upvotes: 10

Related Questions