[Tutor] What protocol to follow when need to pick either one from __getattr__ and __getattribute__ ?
Peter Otten
__peter__ at web.de
Tue Apr 23 13:04:42 EDT 2019
Arup Rakshit wrote:
> I read today 2 methods regarding the customizing the attribute
> access:__getattr__ and __getattribute__ from
> https://docs.python.org/3/reference/datamodel.html#special-method-names.
> What I understood about them is that __getattr__ is called when the
> requested attribute is not found, and an AttributeError is raised. But
> later is called everytime unconditionally. I wrote a simple 2 input
> calculator program, where only 2 operations are permitted Addition and
> Subtraction. Anything else will cause an not permitted error.
>
> class OperationNotPermitted(AttributeError):
> pass
>
> class Calc:
> def __init__(self, x, y):
> self.x = x
> self.y = y
>
> def __getattr__(self, name):
> if name == "sum":
> return self.x + self.y
> elif name == 'minus':
> return self.x - self.y
> else:
> raise OperationNotPermitted("operation {} is not
> permitted".format(name))
>
> And here is a run down:
>
> from customize_attr_access import *
> cal = Calc(12, 10)
> cal.sum
> 22
> cal.minus
> 2
> cal.mul
> Traceback (most recent call last):
> Python Shell, prompt 5, line 1
> # Used internally for debug sandbox under external interpreter
> File "/Users/aruprakshit/python_playground/customize_attr_access.py",
> line 15, in __getattr__
> raise OperationNotPermitted("operation {} is not
> permitted".format(name))
> customize_attr_access.OperationNotPermitted: operation mul is not
> permitted
>
> If I replace __getattr__ with __getattribute__ I found the program works
> exactly same.
No, it doesn't, as __getattribute__ is called for x, and y, too.
def __getattribute__(self, name):
if name == "sum":
return self.x + self.y
elif name == 'minus':
return self.x - self.y
else:
raise OperationNotPermitted("operation {} is not permitted".format(name))
Accessing cal.sum will therefore trigger a __getattribute__("x") call which in turn will raise an OperationNotPermitted("operation x ...")
exception.
> Now my questions is in real world when you have to pick
> between these 2 pair of special method which protocols a Python dev
> checks to pick either of the one? Is there any such thing, or either one
> is fine. Can anyone elaborate this to educate me please?
__getattribute__() is rarely needed, __getattr__() is useful when the
list of calculated attributes is open-ended and uniform (think proxy).
When there is a finite number of calculated attributes the best way to
implement them is usually a property:
class Calc:
def __init__(self, x, y):
self.x = x
self.y = y
@property
def sum(self):
return self.x + self.y
@property
def difference(self):
return self.x - self.y
>
> doc said:
>
> > This method should either return the (computed) attribute value or
> raise an AttributeError exception.
>
> Another question:
>
> My question is that: Can I raise a domain error like
> OperationNotPermitted when raising instead of AttributeError ?
You just did ;) I don't think it's a good idea, though.
More information about the Tutor
mailing list