1

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?

2 Answers 2

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:

  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
Sign up to request clarification or add additional context in comments.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.