RomaValcer
RomaValcer

Reputation: 2956

Static class attributes with Python 3

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?

Upvotes: 1

Views: 388

Answers (2)

MSeifert
MSeifert

Reputation: 152647

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

Upvotes: 3

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160417

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:

  1. More portable granted you explicitly inherit from object in your class definitions.
  2. 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

Upvotes: 4

Related Questions