[Cython] Class scope lookup order

Stefan Behnel stefan_ml at behnel.de
Mon Aug 15 12:42:14 CEST 2011


Vitja Makarov, 15.08.2011 11:55:
> 2011/8/15 Stefan Behnel:
>> Stefan Behnel, 15.08.2011 11:34:
>>>
>>> at least to me, the most surprising thing is this:
>>>
>>>   >>>  A = 1
>>>   >>>  def foo(x):
>>>   ...   A = x
>>>   ...   class X:
>>>   ...     a = A
>>>   ...   return X
>>>   ...
>>>   >>>  foo(2).a
>>>   2
>>>   >>>  def foo(x):
>>>   ...   A = x
>>>   ...   class X:
>>>   ...     A = A
>>>   ...   return X
>>>   ...
>>>   >>>  foo(2).A
>>>   1
>>>
>>> That looks pretty sick, but I would guess that the 'reasoning' behind this
>>> is that the second case contains an assignment to A inside of the class
>>> namespace, and assignments make a variable local to a scope, in this case,
>>> the function scope.
>>
>> Argh, sorry, I interpreted the results the wrong way around.

... or rather used the right reasoning to draw the wrong conclusion. ;)

Ok, so there's an assignment in the second case, which makes A local to the 
class scope, thus overriding the definition in the function scope. Now, 
when it's being looked up at runtime, it's not in the class locals, so the 
lookup falls through to the globals. In the first case, it's not defined in 
the class scope at all, so it's taken from the surrounding function scope 
directly (and statically).


> I've tried emulate this behaviour in cython here:
>
> https://github.com/vitek/cython/commit/26ec702fd93fb6dc2109a501b52130e5f775c793

My feeling is that it should rather be a matter of static analysis to 
figure out which is meant, although I think your change mimics what CPython 
does. I guess this would fix #671, right?


> Actually I think this is made to support assignments like A = A in class scope.

This behaviour wouldn't be strictly required for that goal. My guess is 
that it was just simpler to implement in CPython, because it has less 
special cases. Having to look up a name in a series of outer scopes in the 
case that it happens not to be defined in a class scope yet (although it is 
known to get defined therein at some point), or even remembering the right 
scope where it needs to get looked up, is trickier than just falling 
through to the globals.

Stefan


More information about the cython-devel mailing list