On Wed, Nov 30, 2016 at 5:05 PM, Steve D'Aprano
<steve+pyt...@pearwood.info> wrote:
> On Wed, 30 Nov 2016 07:51 pm, Ian Kelly wrote:
>
>> On Wed, Nov 30, 2016 at 1:29 AM, Frank Millman <fr...@chagford.com> wrote:
>
>>> But I found it easy to write my own -
>>>
>>> async def anext(aiter):
>>>    return await aiter.__anext__()
>>
>> Even simpler:
>>
>> def anext(aiter):
>>     return aiter.__anext__()
>
>
> With very few exceptions, you shouldn't be calling dunder methods directly.
>
> Ideally, you should have some function or operator that performs the call
> for you, e.g. next(x) not x.__next__().

Yes, that's what the purpose of this function is.

> One important reason for that is that the dunder method may be only *part*
> of the protocol, e.g. the + operator can call either __add__ or __radd__;
> str(x) may end up calling either __repr__ or __str__.
>
> If such a function doesn't exist, then it's best to try to match Python's
> usual handling of dunders as closely as possible. That means, you shouldn't
> do the method lookup on the instance, but on the class instead:
>
>     return type(aiter).__anext__()
>
> That matches the behaviour of the other dunder attributes, which normally
> bypass the instance attribute lookup.

To be pedantic, it should be more like:

    return type(aiter).__dict__['__anext__']()

The difference between this and the above is that the above would try
the metaclass if it didn't find the method in the class dict, and it
might also call the metaclass's __getattr__ or __getattribute__.

What difference does it really make, though? That dunder methods are
looked up directly on the class is primarily an optimization. It's not
critical to the inner workings of the language.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to