Skip to content

Commit df442c0

Browse files
committed
move __class__ special case out of the fast path
1 parent f161268 commit df442c0

File tree

3 files changed

+31
-11
lines changed

3 files changed

+31
-11
lines changed

Lib/test/test_super.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,23 @@ def method(self):
393393
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
394394
C().method()
395395

396+
def test_super___class__(self):
397+
class C:
398+
def method(self):
399+
return super().__class__
400+
401+
self.assertEqual(C().method(), super)
402+
403+
def test_super_subclass___class__(self):
404+
class mysuper(super):
405+
pass
406+
407+
class C:
408+
def method(self):
409+
return mysuper(C, self).__class__
410+
411+
self.assertEqual(C().method(), mysuper)
412+
396413

397414
if __name__ == "__main__":
398415
unittest.main()

Objects/typeobject.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9370,13 +9370,6 @@ do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj,
93709370
if (su_obj_type == NULL)
93719371
goto skip;
93729372

9373-
/* We want __class__ to return the class of the super object
9374-
(i.e. super, or a subclass), not the class of su->obj. */
9375-
if (PyUnicode_Check(name) &&
9376-
PyUnicode_GET_LENGTH(name) == 9 &&
9377-
_PyUnicode_Equal(name, &_Py_ID(__class__)))
9378-
goto skip;
9379-
93809373
mro = su_obj_type->tp_mro;
93819374
if (mro == NULL)
93829375
goto skip;
@@ -9452,6 +9445,14 @@ static PyObject *
94529445
super_getattro(PyObject *self, PyObject *name)
94539446
{
94549447
superobject *su = (superobject *)self;
9448+
9449+
/* We want __class__ to return the class of the super object
9450+
(i.e. super, or a subclass), not the class of su->obj. */
9451+
if (PyUnicode_Check(name) &&
9452+
PyUnicode_GET_LENGTH(name) == 9 &&
9453+
_PyUnicode_Equal(name, &_Py_ID(__class__)))
9454+
return PyObject_GenericGetAttr(self, name);
9455+
94559456
return do_super_lookup(su, su->type, su->obj, su->obj_type, name, NULL);
94569457
}
94579458

Python/compile.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4237,18 +4237,20 @@ is_import_originated(struct compiler *c, expr_ty e)
42374237
}
42384238

42394239
static int
4240-
can_optimize_super_call(struct compiler *c, expr_ty e)
4240+
can_optimize_super_call(struct compiler *c, expr_ty attr)
42414241
{
4242+
expr_ty e = attr->v.Attribute.value;
42424243
if (e->kind != Call_kind ||
42434244
e->v.Call.func->kind != Name_kind ||
42444245
!_PyUnicode_EqualToASCIIString(e->v.Call.func->v.Name.id, "super") ||
4246+
_PyUnicode_EqualToASCIIString(attr->v.Attribute.attr, "__class__") ||
42454247
asdl_seq_LEN(e->v.Call.keywords) != 0) {
42464248
return 0;
42474249
}
42484250
Py_ssize_t num_args = asdl_seq_LEN(e->v.Call.args);
42494251

42504252
PyObject *super_name = e->v.Call.func->v.Name.id;
4251-
// try to detect statically-visible shadowing of 'super' name
4253+
// detect statically-visible shadowing of 'super' name
42524254
int scope = _PyST_GetScope(c->u->u_ste, super_name);
42534255
if (scope != GLOBAL_IMPLICIT) {
42544256
return 0;
@@ -4388,7 +4390,7 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
43884390
/* Alright, we can optimize the code. */
43894391
location loc = LOC(meth);
43904392

4391-
if (can_optimize_super_call(c, meth->v.Attribute.value)) {
4393+
if (can_optimize_super_call(c, meth)) {
43924394
RETURN_IF_ERROR(load_args_for_super(c, meth->v.Attribute.value));
43934395
int opcode = asdl_seq_LEN(meth->v.Attribute.value->v.Call.args) ?
43944396
LOAD_SUPER_METHOD : LOAD_ZERO_SUPER_METHOD;
@@ -5406,7 +5408,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
54065408
return compiler_formatted_value(c, e);
54075409
/* The following exprs can be assignment targets. */
54085410
case Attribute_kind:
5409-
if (e->v.Attribute.ctx == Load && can_optimize_super_call(c, e->v.Attribute.value)) {
5411+
if (e->v.Attribute.ctx == Load && can_optimize_super_call(c, e)) {
54105412
RETURN_IF_ERROR(load_args_for_super(c, e->v.Attribute.value));
54115413
int opcode = asdl_seq_LEN(e->v.Attribute.value->v.Call.args) ?
54125414
LOAD_SUPER_ATTR : LOAD_ZERO_SUPER_ATTR;

0 commit comments

Comments
 (0)