Suppose I have the following class
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
As an example, I want the following results where all values have been multiplied by 10:
Headings.standard_heading
>>> {
'height': 37.2,
'width': 256.8,
'left': 16.5,
'top': 2.8
}
Is there no way to override the calling of a class attribute by adding a method similar to this to the class:
def __getattribute__(cls, attr):
return {k:v*10 for k,v in attr.items()
I won't ever be creating instances of this class. I just use it for grouping purposes.
Thanks
You almost had it - just define it the getter as a class method (also you had a small syntax error, attr
is a string here):
class Headings:
standard_heading = {
'height': 3.72,
'width': 25.68,
'left': 1.65,
'top': 0.28
}
@classmethod
def __getattribute__(cls,attr):
return {k:v*10 for k,v in cls.__dict__[attr].items()}
print(Headings().standard_heading)
Note you do need an actual instance for this to work, but that's what you use in your example. This will also ruin get attribute for object specific fields defined within any method of the object (such as __init__
), so careful with this. An easy fix is to override also:
@classmethod
def __getattribute__(cls,attr):
try:
return {k:v*10 for k,v in cls.__dict__[attr].items()}
except: raise AttributeError(attr)
def __getattr__(self,attr):
return object.__getattribute__(self,attr)
So now if you have:
def __init__(self): self.a = 'abc'
then
print(Headings().a)
will also work. Explanation:
__getattribute__
is called as a class method.__getattr__
is invoked, now as a regular method, so with the actual object (and object members).object
__getattribute__
to fall back to normal behavior.Last note - other than your specific question, if you just want to define a special getter
for one class member, a safer way that will only affect said member is using @property
and @getter
-as explained for example in How does the @property decorator work?. Thanks Adonis for pointing that out.