Issue 25634: Add a dedicated subclass for attribute missing errors (original) (raw)
Created on 2015-11-16 09:39 by Jun Wang, last changed 2022-04-11 14:58 by admin. This issue is now closed.
Messages (5)
Author: Jun Wang (Jun Wang)
Date: 2015-11-16 09:39
See this simple example:
class A(): def init(self, x=None): self.x = x
@property
def t(self):
return self.x.t
def __getattr__(self, name):
return 'default'
print(A().t)
AttributeError is raised as "'NoneType' object has no attribute 't'". Currently getattr is called if any AttributeError is raised, so the result of a.t is default, while an AttributeError is the desired behavior.
The most intuitive solution seems to add a subclass of AttributeError, say AttributeMissError, which triggers getattr. At present, I have to do some tricky and ugly things to getattribute to show where the AttributeError occurs, or it's quite hard to figure out what happened with no informative traceback messages.
Author: R. David Murray (r.david.murray) *
Date: 2015-11-16 14:50
I understand what you are concerned about, but unfortunately that would be a significant backward compatibility break. This would need discussion on python-ideas, I think. Even aside from the backward compatibility issue I have a feeling the additional complexity this would add to attribute resolution would be deemed too large to be worthwhile, but I haven't looked at the relevant code so I might be wrong.
Author: Jun Wang (Jun Wang)
Date: 2015-11-19 19:47
I think this is a common problem while using both getattr and descriptor/property. A descriptor example:
class Descriptor(): def get(self, instance, owner=None): raise AttributeError('Implicitly suppressed')
class A(): d = Descriptor() def getattr(self, name): return 'default'
print(A().d)
Without descriptor, unexpected AttributeError could only come from overriding getattribute, which is a rare case, although still an imperfection. But in descriptor/property, AttributeError which is too general just occurs frequently like in normal method.
Surely any modification would break the backward compatibility, although I wonder how often it is used of raising AttributeError purposely, maybe in getattribute, to call getattr, instead of explicitly calling getattr. In my understanding this is the only case that will be affected.
"An unexpected exception should not result in subtly altered behaviour, but should cause a noisy and easily-debugged traceback. "—from PEP479
About the implementation, maybe something like "RuntimeError: descriptor raised AttributeError" simulating PEP479. Or in my lay opinion, the best solution is: add object.getattr, with the only behavior of raising AttributeError; when normal attribute lookup fails, object.getattribute calls getattr explicitly; getattr not triggered by AttributeError anymore.
I know little about the CPython implementation, so I might be completely wrong. However this seems deserving more detailed discussion.
Author: R. David Murray (r.david.murray) *
Date: 2015-11-19 19:56
The more detailed discussion should happen on python-ideas. I'm going to close this for now, but if there's a consensus there about what action to take this issue could be reopened. (Or a new one created, whatever makes the most sense at that time.)
Author: Ethan Furman (ethan.furman) *
Date: 2015-11-28 15:32
Note for posterity: the current behavior of getattr is what allows Enum to work correctly.
History
Date
User
Action
Args
2022-04-11 14:58:23
admin
set
github: 69820
2015-11-28 15:32:07
ethan.furman
set
nosy: + ethan.furman
messages: +
2015-11-19 19:56:57
r.david.murray
set
status: open -> closed
resolution: later
messages: +
stage: resolved
2015-11-19 19:47:33
Jun Wang
set
messages: +
2015-11-16 14:50:13
r.david.murray
set
nosy: + r.david.murray
messages: +
2015-11-16 09:39:59
Jun Wang
create