New submission from Nick Coghlan:

In http://bugs.python.org/issue28884#msg282535 Armin Rigo points out that the 
zero-argument super() cell injection currently interacts a little strangely 
with explicit "nonlocal __class__" statements in nested namespaces.

Specifically, it acts like a closure variable that isn't visible in its own 
scope, but can be accessed via nonlocal in nested class scopes:

>>> class C_with_nested_nonlocal:
...     class Inner:
...         nonlocal __class__
...         __class__ = 42
...     print(locals())
...
{'__module__': '__main__', '__qualname__': 'C_with_nested_nonlocal', 'Inner': 
<class '__main__.C_with_nested_nonlocal.Inner'>, '__class__': 42}

This weird behaviour is due to the way the CPython code generator injects 
__class__ into the namespaces we track during symbol table generation 
(specifically, it's made available as a free variable for nested namespaces to 
reference without actually adding it to the local symbol namespace for the 
class body). There's no requirement for other implementations to replicate the 
full details of that idiosyncratic behaviour, but there is a requirement that 
__class__ and (in 3.6+) __classcell__ not show up in locals() by default when 
evaluating the class body.

And methods can similarly overwrite the interpreter provided reference to the 
defining class:

>>> class C_with_method_assignment_to_class_cell:
...     def bad_method(self):
...         nonlocal __class__
...         __class__ = 42
...     def other_method(self):
...         return __class__
...     bad_method(None)
...     print(locals()["__class__"])
... 
42
>>> C_with_method_assignment_to_class_cell().other_method()
<class '__main__.C_with_method_assignment_to_class_cell'>
>>> C_with_method_assignment_to_class_cell().bad_method()
>>> C_with_method_assignment_to_class_cell().other_method()
42

One possible approach here would be to implement an outright language level ban 
on the use of "__class__" in explicit "nonlocal" declarations, and then add a 
test to Lib/test_super.py that ensures "__class__" and "__classcell__" don't 
show up in the class locals() while the statement body is executing.

----------
messages: 282585
nosy: arigo, ncoghlan
priority: normal
severity: normal
stage: test needed
status: open
title: Standardise more behaviours for zero-argument super() __class__ and 
__classcell__
type: behavior

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue28891>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to