[New-bugs-announce] [issue28891] Standardise more behaviours for zero-argument super() __class__ and __classcell__

Nick Coghlan report at bugs.python.org
Tue Dec 6 20:24:28 EST 2016


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 <report at bugs.python.org>
<http://bugs.python.org/issue28891>
_______________________________________


More information about the New-bugs-announce mailing list