Đây là một tương tác kỳ lạ trong việc thực hiện không có đối số của Python 3 super
. Quyền truy cập vào super
trong một phương pháp kích hoạt việc thêm biến số đóng ẩn __class__
ẩn tham chiếu đến lớp xác định phương thức. Trường hợp đặc biệt của trình phân tích cú pháp tải trọng tên super
trong một phương pháp bằng cách thêm __class__
vào bảng biểu tượng của phương thức và sau đó phần còn lại của mã có liên quan đều tìm kiếm __class__
thay vì super
. Tuy nhiên, nếu bạn cố gắng tự mình truy cập vào __class__
, tất cả mã tìm kiếm __class__
sẽ thấy nó và cho rằng cần xử lý super
!
Here's where it adds the name __class__
to the symbol table if it sees super
:
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;
Dưới đây là drop_class_free
, đặt ste_needs_class_closure
:
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;
}
Các compiler section để kiểm tra ste_needs_class_closure
và tạo ra các tế bào tiềm ẩn:
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;
}
...
Có nhiều lại mã levant, nhưng nó quá nhiều để bao gồm tất cả. Python/compile.c
và Python/symtable.c
là nơi cần tìm nếu bạn muốn xem thêm.
Bạn có thể nhận được một số lỗi lạ nếu bạn cố gắng sử dụng một biến có tên __class__
:
class Foo:
def f(self):
__class__ = 3
super()
Foo().f()
Output:
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
Việc chuyển nhượng để __class__
nghĩa __class__
là một biến địa phương thay vì đóng cửa biến, do đó, các tế bào đóng cửa super()
nhu cầu không có.
def f():
__class__ = 2
class Foo:
def f(self):
print(__class__)
Foo().f()
f()
Output:
<class '__main__.f.<locals>.Foo'>
Mặc dù có một __class__
biến thực tế trong phạm vi kèm theo, các chuyên vỏ của __class__
có nghĩa là bạn có được lớp thay vì giá trị biến phạm vi bao quanh của.
Đây là tài liệu *? Vâng, bây giờ tôi cảm thấy ngớ ngẩn về đào bới thông qua nguồn cho việc này. Đây là một câu trả lời tốt hơn tôi. – user2357112
Câu trả lời không thực sự giải thích cho tôi tại sao tài liệu tham khảo cần phải được tạo khi siêu không được sử dụng. – wim
@wim: Không cần tạo. Nó chỉ là anyway. Tôi đoán việc thực hiện chỉ xảy ra để làm việc theo cách đó và sau đó họ ghi lại nó bởi vì nó không phải là một thỏa thuận đủ lớn để có giá trị thay đổi, thay vì điều này là do thiết kế. – user2357112