[Python-ideas] The AttributeError/__getattr__ mechanism
王珺
wjun77 at gmail.com
Fri Nov 27 18:23:13 EST 2015
> This would create a boundary, same as PEP 479 does for StopIteration,
> across which AttributeError becomes RuntimeError.
Although my problem is about property as I don't use descriptor here, I
think descriptor other than property should also be considered, such as
classmethod/staticmethod, and normal descriptor. Raising "RuntimeError:
descriptor raised AttributeError" is acceptable for me, but maybe some c
code need modification, I don't know.
> Do you have any examples that actually do demonstrate the problem to be
solved?
So you want more details about AttributeError in property? I thought
property is widely used, and AttributeError occurs at all times. Maybe I've
used property too heavy.
In the window example, a simplified demonstration:
class Window():
@property
def backgroundImg(self):
if self._backgroundImg is None: #need update, while the number of
items changes
self.set_backgroundImg()
return self._backgroundImg
def set_backgroundImg(self):
self._backgroundImg = loadImg('white.bmp')
for widget in self.widgets:
widget.show(self._backgroundImg)
Class Widget():
def show(self, img):
img.draw(self.item.img, self.pos)
However, widget.item may be None, while e.g. there are four widgets but
only three items in total. In this case I should fill the area with white.
But in this version of *show*, I just FORGET item can be None. So the
traceback infomation: 'Window' object has no attribute 'backgroundImg'. In
fact it takes a while before I find the cause is the
AttributeError/__getattr__ mechanism.
> But surely breaking that isn't the same as breaking code that's been
explicitly stated to work, and used as sample code, for decades.
I don't know this is such a severe problem. I used to think raising
AttributeError in __getattribute__ to trigger __getattr__ is rare.
> any solution that can fix descriptors without also "fixing"
__getattribute__ is a lot better
In practice I don't concern __getattribute__. But in my opinion it's better
to 'fix' this in python4.
> all of your solutions make it too hard to trigger __getattr__ from a
descriptor when you really _do_ want to do so
This is a big problem, OK.
> You didn't comment on the alternative I suggested; would it not satisfy
your needs, or have some other problem that makes it unacceptable?
I don't quite understand, you mean adding a subclass of *object* with the
only difference of this behavior?
2015-11-28 5:37 GMT+08:00 Andrew Barnert <abarnert at yahoo.com>:
> On Nov 27, 2015, at 12:18, 王珺 <wjun77 at gmail.com> wrote:
>
> I think the real world use case, as *property* is so common, is just when
> __getattr__ needed. So anyone using __getattr__ in practice?
>
>
> Your own examples seem like reasonable uses of __getattr__ to me. But they
> don't demonstrate your problem, because you don't have any properties,
> other custom descriptors, or __getattribute__. Do you have any examples
> that actually do demonstrate the problem to be solved?
>
> > Is that really an imperfection? It says right there in the docs for
> __getattribute__ that you can delegate to __getattr__ by raising
> AttributeError
> Just like raising *StopIteration* in generator, as described in PEP479.
>
>
> But the docs didn't recommend raising StopIteration to exit a generator.
> The docs implied it by omission, or at least we're ambiguous about what
> would happen, and you could test it and see that it did, which meant some
> people took advantage of it to do things like using a
> StopIteration-throwing function in a comprehension filter clause (with
> caveats about listcomp vs. genexpr and 2.x vs. 3.x and most readers having
> to guess why it works). But surely breaking that isn't the same as breaking
> code that's been explicitly stated to work, and used as sample code, for
> decades.
>
> Although I'm not sure *StopIteration* has ever been documented as one way
> to exit generator. And I admit that an unintentional AttributeError in
> __getattribute__ is a rare case if ever.
>
>
> That's my point: "fixing" __getattribute__ to eliminate a "rare case if
> ever" bug, while also introducing a possibly less-rare backward
> compatibility problem, seems like a terrible idea. Of course that isn't
> your intention; it's just a side effect of trying to eliminate a more
> common bug, with probably rarer intentional uses, in descriptors. But to
> me, that implies that any solution that can fix descriptors without also
> "fixing" __getattribute__ is a lot better. And, as you imply in the bug
> report, this could be done by having either the descriptor mechanism
> itself, or the object.__getattribute__ implementation, handle
> AttributeError from descriptor lookup by reraising it as something else.
>
> But still, this is all a minor side issue about choosing between your
> different variations. The big problem is that I think all of your solutions
> make it too hard to trigger __getattr__ from a descriptor when you really
> _do_ want to do so. Maybe you don't want to do so very often, but is it
> really so rare that we can justify making it impossible? (Especially
> considering the backward-compat issues for any code that's been doing that
> for years...)
>
> You didn't comment on the alternative I suggested; would it not satisfy
> your needs, or have some other problem that makes it unacceptable?
>
> 2015-11-28 2:34 GMT+08:00 Andrew Barnert <abarnert at yahoo.com>:
>
>> It seems like you can get some of the benefits of this proposal without
>> backward compat issues.
>>
>> Instead of changing things so AttributeError from __getattribute__ or a
>> descriptor no longer calls __getattr__, just add a new subclass that
>> doesn't, and change the Descriptor HOWTO to suggest using that subclass
>> (with a bit of discussion that says you can use AttributeError if you want
>> to trigger __getattr__, but usually you won't).
>>
>> That wouldn't fix any current code, but it also wouldn't break any code
>> that intentionally uses the features as documented. And it would make it
>> easy to write correct new code.
>>
>> One more thing:
>>
>> Without descriptor, unexpected AttributeError could only come from overriding __getattribute__, which is a rare case, although still an imperfection.
>>
>> Is that really an imperfection? It says right there in the docs for
>> __getattribute__ that you can delegate to __getattr__ by raising
>> AttributeError, so if someone does that, presumably it's intentional. It's
>> not like the case with descriptors, where you have to think through the
>> interaction of multiple features to figure out that raising an
>> AttributeError will call __getattr__, and therefore many such uses are
>> probably bugs.
>>
>> Sent from my iPhone
>>
>> On Nov 27, 2015, at 09:49, 王珺 <wjun77 at gmail.com> wrote:
>>
>> Hello everyone:
>>
>> I'm suggesting a modification to the AttributeError/__getattr__
>> mechanism, see issue25634:
>> http://bugs.python.org/issue25634
>>
>> I used __getattr__ sometimes, and descriptor especially property is so
>> widely used. I wonder whether someone had encountered the same problem with
>> me.
>>
>> However, this is a complicated problem including performance issues, and
>> backward compatibility.
>>
>> Thanks for your attention,
>> Jun Wang
>>
>> _______________________________________________
>> Python-ideas mailing list
>> Python-ideas at python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20151128/5c93f2dd/attachment.html>
More information about the Python-ideas
mailing list