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