On 28/06/2019 02:13, adam.pre...@gmail.com wrote:
I'm trying to mimick Python 3.6 as a .NET science project and have started to
get into subclassing. The super() not-a-keyword-honestly-guys has tripped me
up. I have to admit that I've professionally been doing a ton Python 2.7, so
I'm not good on my Python 3.6 trivia yet. I think I have the general gist of
this, but want some affirmation.
If you use super() in a method, all it does is load super as a global on to the
interpreter stack and call it without any arguments. So I'm left to wonder how
it's able to figure anything out when it's being literally given nothing...
Python is open source, so let's open the source!
The magic happens when super() is constructed, in super_init
https://github.com/python/cpython/blob/a8b27e623d75377aabe50df27e97cab4e81a174a/Objects/typeobject.c#L7814
Once super_getattro is called, the super object has already been set up,
and it already knows which object/class to look at.
As you can see, super_init takes the calling frame and checks the first
argument of the previous call, which, when called from a method, will
generally be 'self'
https://github.com/python/cpython/blob/a8b27e623d75377aabe50df27e97cab4e81a174a/Objects/typeobject.c#L7849
There's some additional code that, I think, handles being called from a
closure (but I don't know the C api well enough to be sure)
We can sort-of emulate this in pure Python with the inspect module
###
def not_quite_super():
f = inspect.stack()[1].frame
obj = list(f.f_locals.values())[0]
print(type(obj), obj)
class A:
def __init__(self, a=0, b=1):
c = a + b # this is just to add some more locals to the mix
not_quite_super()
A()
###
Once you have the caller object, the rest is just like calling super()
with arguments.
I'm not actually sure that Python example above is guaranteed to work,
but I *think* it should in versions where dicts are ordered (3.6+).
Obviously it doesn't handle all the cases super() handles.
except that it's not being given literally nothing:
static PyObject *
super_getattro(PyObject *self, PyObject *name)
I was thinking maybe self has become more special in Python 3.6, but I don't think that's
true since I've ported code to Python3 before that had inner classes where I'd use
"inner_self" to disambiguate with the outer self. And though I thought it was
so at first, it just turned out I screwed up my little code snippet to expose it. If self
was special then I presume I could find it in my lookups and inject it.
So how do I go from CALL_FUNCTION on a super() global without anything else on
the stack to somehow having all the information I need? Is there something
tracking that I'm in an object scope when calling stuff?
--
https://mail.python.org/mailman/listinfo/python-list