This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Global scoping when shadowing local names in class definitions
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.8, Python 3.7, Python 3.6, Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: antoine.pietri, anton.barkovsky, multun, terry.reedy
Priority: normal Keywords:

Created on 2018-10-11 19:15 by multun, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
weird_class_scope.py multun, 2018-10-11 19:15 A broader example, demonstrating it only works with classes, and the scope the variable comes from is global
Messages (4)
msg327547 - (view) Author: multun (multun) Date: 2018-10-11 19:15
Hello,

>>> a="global"
>>> def func(a):
...     class wtf():
...             a=a
...     return wtf
... 
>>> func("local").a
'global'
>>> def func2(a):
...     class wtf():
...             b=a
...     return wtf
... 
>>> func2("local").b
'local'


Is this behavior legit ?

Best regards,

--
Victor "multun" Collod
msg327588 - (view) Author: Antoine Pietri (antoine.pietri) * Date: 2018-10-12 14:33
Tracking down the issue a bit further:

    a = 10


    def main():
        a = 42

        class wtf():
            print(a)

        class wtf2():
            print(a)
            a = 2


    main()

prints:

    42
    10


It seems that when there is an assignation in the class body, prior usages of the variables in the class body are done by loading the variable using LOAD_NAME instead of LOAD_CLASSDEREF:


Disassembly of <code object wtf at 0x7fa1b8b01390, file "lolmul.py", line 7>:
[...]

  8           8 LOAD_NAME                3 (print)
             10 LOAD_CLASSDEREF          0 (a)
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               1 (None)
             18 RETURN_VALUE

Disassembly of <code object wtf2 at 0x7fa1b8b018a0, file "lolmul.py", line 10>:
[...]

 11           8 LOAD_NAME                3 (print)
             10 LOAD_NAME                4 (a)
             12 CALL_FUNCTION            1
             14 POP_TOP

 12          16 LOAD_CONST               1 (2)
             18 STORE_NAME               4 (a)
             20 LOAD_CONST               2 (None)
             22 RETURN_VALUE
msg327607 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2018-10-12 18:17
Questions about whether basic syntax behavior is correct should be asked elsewhere, such as python-list.  A proper answer requires a careful reading of the doc and a non-trivial answer.  Someone on python-list should do that.

Classes and scoping are known to have some non-intuitive corner cases.  Quite aside from the fact that the default assumption should be that the implementation of heavily used syntax is correct, my memory is that what you see is correct.  But I have not read the appropriate parts of the doc for a few years.

PS.  3.4 and 3.5 currently only get security fixes.  The same will be true of 3.6 sometime next year.
msg327612 - (view) Author: multun (multun) Date: 2018-10-12 20:56
Closing, this is documented, and as such most likely intended.

"A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace."
https://docs.python.org/3.7/reference/executionmodel.html#builtins-and-restricted-execution
History
Date User Action Args
2022-04-11 14:59:07adminsetgithub: 79142
2018-10-12 20:56:52multunsetstatus: open -> closed
versions: + Python 2.7, Python 3.4, Python 3.5
messages: + msg327612

resolution: not a bug
stage: resolved
2018-10-12 18:17:11terry.reedysetnosy: + terry.reedy

messages: + msg327607
versions: - Python 2.7, Python 3.4, Python 3.5
2018-10-12 14:33:42antoine.pietrisetnosy: + antoine.pietri
messages: + msg327588
2018-10-12 11:18:22anton.barkovskysetnosy: + anton.barkovsky
2018-10-11 19:15:04multuncreate