I need to define custom attributes for a class, but redefining __getattr__
works only for the instance, not for the class itself, and making it static doesn't really help. I know that something like this works for Python 2, but I couldn't find anything similar on Python 3, I suspect due to changing the way metaclasses work. How would I achieve similar result?
Asked
Active
Viewed 350 times
1

Community
- 1
- 1

RomaValcer
- 2,786
- 4
- 19
- 29
2 Answers
4
You need to change the way you specify metaclasses in Python 3. It was changed from a dunder attribute __metaclass__
to a kwarg
you supply after the base classes. Other than that, the solution provided there suffices:
class MyClass(metaclass = FooType): pass
Now MyClass.Foo
or MyClass.Bar
call the methods _foo_func
and _bar_func
respectively.
Note that the custom descriptor object, the second answer in the linked question, is:
- More portable granted you explicitly inherit from
object
in your class definitions. - More maintainable than creating a custom metaclass. Metaclasses might lead to confusion and weird conflicts down the line, descriptors are simple after you get a hang of them

Dimitris Fasarakis Hilliard
- 150,925
- 31
- 268
- 253
3
Adding to Jims answer: If you need Python2 and 3 compatibility you can use the six.add_metaclass
class decorator:
import six
@six.add_metaclass(your_metaclass)
class Yourclass(): # no need to add "metaclass = your_metaclass" here!
# no need to define "__metaclass__ = your_metaclass" here
Like the documentation states, this:
@six.add_metaclass(Meta)
class MyClass(object):
pass
is identical to (python2):
class MyClass(object):
__metaclass__ = Meta
or (python3):
class MyClass(object, metaclass=Meta):
pass

MSeifert
- 145,886
- 38
- 333
- 352