[Cython] Class scope lookup order

Vitja Makarov vitja.makarov at gmail.com
Mon Aug 15 19:11:22 CEST 2011


2011/8/15 Vitja Makarov <vitja.makarov at gmail.com>:
> 2011/8/15 Stefan Behnel <stefan_ml at behnel.de>:
>> 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?
>>
>
> Yes. And I use CF info in my commit.
>
>>
>>> 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.
>>
>
> It's documented here:
>
> http://docs.python.org/reference/executionmodel.html#interaction-with-dynamic-features
>
> """
> Names may be resolved in the local and global namespaces of the
> caller. Free variables are not resolved in the nearest enclosing
> namespace, but in the global namespace.
> """
>
>

I think I'm done with the issue and if you don't mind I'll push that.

https://github.com/vitek/cython/commit/b4a0493efbae68b30d54f0c58311c71465d57d43

-- 
vitja.


More information about the cython-devel mailing list