[Python-Dev] Intricacies of calling __eq__

Terry Reedy tjreedy at udel.edu
Wed Mar 19 02:29:05 CET 2014


On 3/18/2014 9:09 PM, Steven D'Aprano wrote:

> Currently, the code:
>
>      if key in dict:
>          return dict[key]
>
>
> performs two dictionary lookups. If you read the code, you can see the
> two lookups: "key in dict" performs a lookup, and "dict[key]" performs a
> lookup.

The doc says that

@deco
def f(): pass

is equivalent to

def f(): pass
f = deco(f)

That clearly implies two assignments to the containing namespace. But 
CPython only does one. It actually does something like

def <internal function reference>(): pass
f = deco(<internal function reference>)

This can be detected by defining deco to have the side-effect of 
checking the local namespace for a binding to 'f' (actually, <internal 
function reference>.__name__) and reporting via print() before 
returning. When someone did detect the difference and filed a bug 
report, Guido declared that the difference did not matter and that the 
current behavior is close enough to meeting the as-if rule.

Optimizing away a dict lookup strikes me as similar to optimizing away a 
namespace binding, which is typically a dict setting, which would 
involve a dict lookup. In fact, I imagine that your test class with a 
__eq__ method that reports calls would be an alternate way to detect the 
@deco optimization.

-- 
Terry Jan Reedy



More information about the Python-Dev mailing list