4 ms·
> Therefore, if a method is copied from one class to another, `super` within that method may refer to the wrong class. No, super() checks that "self" is an ins
by blattimwind 7y ago
> Therefore, if a method is copied from one class to another, `super` within that method may refer to the wrong class.
No, super() checks that "self" is an instance of the given class.
So if you take a method defined in a class hierarchy "A -> B", and attach it to an instance of "C" (i.e. c.foo = B.foo) and call it like "c.foo(c)", which you have to do, since you didn't invoke the descriptor protocol to bind the method, you will get a type error, because c is not an instance of A/B. That is also true if you attach the method to the class (C.foo = B.foo); you can call it like a method, but super() still checks the type and will complain.
Also, if you take a bound method and attach it to another object (i.e. c.foo = b.foo), it is already bound and you can't pass a "self" different from the object it's bound to. E.g. if you are passing around a callback that's a method.
Note how Class.method is just a function, while instance.method is a bound method. That's due to the descriptor protocol of functions (__get__/__set__).
- pansa2 7y ago> That is also true if you attach the method to the class (C.foo = B.foo); you can call it like a method, but super() still checks the type and will complain. You're right. Here's some example Python code: >>> class A: ... def foo(self): ... print('A.foo') >>> class B(A): ... def foo(self): ... super().foo() ... print('B.foo') >>> b = B() >>> b.foo() A.foo B.foo >>> class C: ... def foo(self): ... print('C.foo') >>> class D(C): ... def foo(self): ... super().foo() ... print('D.foo') >>> d = D() >>> d.foo() C.foo D.foo Now, if I do `D.foo = B.foo` and call `d.foo()`, I do indeed get a "TypeError: super(type, obj): obj must be an instance or subtype of type". That's better than getting `A.foo B.foo`, as happens in JavaScript. However, if `super` were truly dynamic, I would have expected to get `C.foo B.foo`.
- blattimwind 7y agoIIRC super() is actually syntactic sugar for super(ClassTheDefIsFoundIn, nameOfFirstArgument), because there is no way I can think of to implement that as a function at runtime.
- pansa2 7y agoYes, I think that’s right. However, I think it would work better if classTheDefIsFoundIn were resolved dynamically rather than lexically. Perhaps it would have been possible to do this by modifying the descriptor protocol?
- blattimwind 7y agoI'm not sure that's possible, because you could only work with type(self), and that breaks MRO traversal. (A chain of super().x() calls in a hierarchy like A->B->C would always call the first parent class, because it has no way to tell >where< in the hierarchy it is. That's the reason why the class argument is required.) I think that would need an entirely differently designed mechanism and can't be bolted on.