Schr?dinger's variable: the __class__ cell magically appears if you're checking for its presence?
这里有一个惊喜:
1 2 3 4 5 6 7 8 9 10 | >>> class B: ... print(locals()) ... def foo(self): ... print(locals()) ... print(__class__ in locals().values()) ... {'__module__': '__main__', '__qualname__': 'B'} >>> B().foo() {'__class__': <class '__main__.B'>, 'self': <__main__.B object at 0x7fffe916b4a8>} True |
似乎仅仅提到
1 | NameError: name '__class__' is not defined |
实际上,如果您修改为只检查密钥,即检查
如何将这个变量神奇地注入作用域?我猜这与
这是Python3实现无参数
这里是它在符号表中添加名称
1 2 3 4 5 6 7 8 9 10 11 12 13 | case Name_kind: if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id,"super")) { if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, USE)) VISIT_QUIT(st, 0); } break; |
这是
1 2 3 4 5 6 7 8 9 10 11 12 13 | static int drop_class_free(PySTEntryObject *ste, PyObject *free) { int res; if (!GET_IDENTIFIER(__class__)) return 0; res = PySet_Discard(free, __class__); if (res < 0) return 0; if (res) ste->ste_needs_class_closure = 1; return 1; } |
检查
1 2 3 4 5 6 7 8 9 10 11 12 13 | if (u->u_ste->ste_needs_class_closure) { /* Cook up an implicit __class__ cell. */ _Py_IDENTIFIER(__class__); PyObject *tuple, *name, *zero; int res; assert(u->u_scope_type == COMPILER_SCOPE_CLASS); assert(PyDict_Size(u->u_cellvars) == 0); name = _PyUnicode_FromId(&PyId___class__); if (!name) { compiler_unit_free(u); return 0; } ... |
有更多相关的代码,但是太多了,无法包含所有代码。如果你想看更多的话,你可以去看
如果尝试使用名为
1 2 3 4 5 6 | class Foo: def f(self): __class__ = 3 super() Foo().f() |
输出:
1 2 3 4 | Traceback (most recent call last): File"./prog.py", line 6, in <module> File"./prog.py", line 4, in f RuntimeError: super(): __class__ cell not found |
对
1 2 3 4 5 6 7 8 9 | def f(): __class__ = 2 class Foo: def f(self): print(__class__) Foo().f() f() |
输出:
1 | <class '__main__.f.<locals>.Foo'> |
即使封闭范围中有一个实际的
https://docs.python.org/3/reference/datamodel.html创建类对象
__class__ is an implicit closure reference created by the compiler if any methods in a class body refer to either__class__ or super. This allows the zero argument form ofsuper() to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method.