Re: [Tutor] What protocol to follow when need to pick either one from __getattr__ and __getattribute__ ?

2019-04-23 Thread Alan Gauld via Tutor
On 23/04/2019 15:52, Arup Rakshit wrote:

> If I replace __getattr__ with __getattribute__ I found the program works 
> exactly same. 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?

There are some recomendations but I'll leave it to someone
better qualified than me to respond.

> Another question:
> 
> My question is that: Can I raise a domain error like 
> OperationNotPermitted when raising instead of AttributeError ?

You can raise any kind of error you like however, in general, using the
standard error types is better because if your class gets using in
another program that already handles the standard error type then your
class will get handled too. But, if you raise a non standard error, it
may slip through the net. (You can mitigate this by subclassing from the
standard error that would normally be raised since catch will catch all
subclasses as swell as the stated exception type.)

HTH
-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] What protocol to follow when need to pick either one from __getattr__ and __getattribute__ ?

2019-04-23 Thread Peter Otten
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.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] What protocol to follow when need to pick either one from __getattr__ and __getattribute__ ?

2019-04-23 Thread Steven D'Aprano
On Tue, Apr 23, 2019 at 08:22:56PM +0530, 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.


When you overload __getattribute__, your class will be slow because 
**every** attribute lookup has to go through your method, instead of 
only the lookups which fail. And unless you are very careful, you will 
break things:



py> class X(object):
... def __init__(self, x):
... self.x = x
... def __getattribute__(self, name):
... if name is 'x': return self.x
...
py> obj = X(999)
py> obj.x
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 5, in __getattribute__
  [ previous line repeats 332 times ]
RecursionError: maximum recursion depth exceeded while calling a Python 
object



Normally, overriding __getattribute__ is considered a very advanced and 
unusual thing to do.


-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor