__getattr__ for static / class variables in python

I have a class like:

class MyClass: Foo = 1 Bar = 2 

Whenever MyClass.Foo or MyClass.Bar , I need a special method that needs to be called before the value is returned. Is this possible in Python? I know that this is possible if I create an instance of the class and I can define my own __getattr__ method. But my scnenario suggests using this class as such without creating it.

I also need a custom __str__ method, which is called when str(MyClass.Foo) called. Does Python provide such an opportunity?

+56
python class-method getattr
Jul 01 2018-10-10T00:
source share
5 answers

__getattr__() and __str__() for an object are in its class, so if you want to configure these things for the class, you need the class of the class. Metaclass.

 class FooType(type): def _foo_func(cls): return 'foo!' def _bar_func(cls): return 'bar!' def __getattr__(cls, key): if key == 'Foo': return cls._foo_func() elif key == 'Bar': return cls._bar_func() raise AttributeError(key) def __str__(cls): return 'custom str for %s' % (cls.__name__,) class MyClass: __metaclass__ = FooType # in python 3: # class MyClass(metaclass=FooType): # pass print MyClass.Foo print MyClass.Bar print str(MyClass) 

print:

 foo! bar! custom str for MyClass 

And no, an object cannot intercept a request for matching one of its attributes. The object returned for the attribute must define its own __str__() .

+64
Jul 01 '10 at 6:24
source share

(I know this is an old question, but since all the other answers use a metaclass ...)

You can use the following simple classproperty descriptor:

 class classproperty(object): """ @classmethod+@property """ def __init__(self, f): self.f = classmethod(f) def __get__(self, *a): return self.f.__get__(*a)() 

Use it as:

 class MyClass(object): @classproperty def Foo(cls): do_something() return 1 @classproperty def Bar(cls): do_something_else() return 2 
+15
Mar 29 '14 at 9:43
source share

For the first, you need to create a metaclass and define __getattr__() .

 class MyMetaclass(type): def __getattr__(self, name): return '%s result' % name class MyClass(object): __metaclass__ = MyMetaclass print MyClass.Foo 

For the second, no. Calling str(MyClass.Foo) calls MyClass.Foo.__str__() , so you need to return the appropriate type for MyClass.Foo .

+9
Jul 01 '10 at 6:26
source share

Surprised, no one pointed to this:

 class FooType(type): @property def Foo(cls): return "foo!" @property def Bar(cls): return "bar!" class MyClass(metaclass=FooType): pass 

Works:

 >>> MyClass.Foo 'foo!' >>> MyClass.Bar 'bar!' 

(for Python 2.x, change the definition of MyClass to:

 class MyClass(object): __metaclass__ = FooType 

)

What other answers say about str true for this solution: it should be implemented for the actual return type.

+5
Jan 28 '14 at 20:26
source share

Depending on the case, I use this template

 class _TheRealClass: def __getattr__(self, attr): pass LooksLikeAClass = _TheRealClass() 

Then you import and use it.

 from foo import LooksLikeAClass LooksLikeAClass.some_attribute 

This avoids the use of a metaclass and handles some use cases.

0
Sep 21 '18 at 14:37
source share



All Articles