Does any magic happen when I call `super(some_cls)`?

2024/10/5 11:26:50

While investigating this question, I came across this strange behavior of single-argument super:

Calling super(some_class).__init__() works inside of a method of some_class (or a subclass thereof), but throws an exception when called anywhere else.

Code sample:

class A():                                                                                         def __init__(self):                                                         super(A).__init__()  # doesn't throw exceptiona = A()
super(A).__init__()  # throws exception

The exception being thrown is

Traceback (most recent call last):File "untitled.py", line 8, in <module>super(A).__init__() # throws exception
RuntimeError: super(): no arguments

I don't understand why the location of the call makes a difference.

It's well-known that the zero-argument form of super performs magic:

The zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.

However, no such statement exists for the one-argument form of super. On the contrary:

Also note that, aside from the zero argument form, super() is not limited to use inside methods.


So, my question is, what exactly is happening under the hood? Is this the expected behavior?

Answer

In both cases, super(A) gives an unbound super object. When you call __init__() on that, it's being called with no arguments. When super.__init__ is called with no arguments, the compiler tries to infer the arguments: (from typeobject.c line 7434, latest source)

static int
super_init(PyObject *self, PyObject *args, PyObject *kwds)
{superobject *su = (superobject *)self;PyTypeObject *type = NULL;PyObject *obj = NULL;PyTypeObject *obj_type = NULL;if (!_PyArg_NoKeywords("super", kwds))return -1;if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj))return -1;if (type == NULL) {/* Call super(), without args -- fill in from __class__and first local variable on the stack. */

A few lines later: (ibid, line 7465)

    f = PyThreadState_GET()->frame;
...co = f->f_code;
...if (co->co_argcount == 0) {PyErr_SetString(PyExc_RuntimeError,"super(): no arguments");return -1;}

When you call super(A), this inferring behavior is bypassed because type is not None. When you then call __init__() on the unbound super - because it isn't bound, this __init__ call isn't proxied - the type argument is None and the compiler attempts to infer. Inside the class definition, the self argument is present and is used for this purpose. Outside, no arguments are available, so the exception is raised.

In other words, super(A) is not behaving differently depending on where it is called - it's super.__init__() that's behaving differently, and that's exactly what the documentation suggests.

https://en.xdnf.cn/q/70490.html

Related Q&A

How to get unpickling to work with iPython?

Im trying to load pickled objects in iPython.The error Im getting is:AttributeError: FakeModule object has no attribute WorldAnybody know how to get it to work, or at least a workaround for loading obj…

Basic questions about nested blockmodel in graph-tool

Very briefly, two-three basic questions about the minimize_nested_blockmodel_dl function in graph-tool library. Is there a way to figure out which vertex falls onto which block? In other words, to ext…

How to get multiple parameters with same name from a URL in Pylons?

So unfortunately I find myself in the situation where I need to modify an existing Pylons application to handle URLs that provide multiple parameters with the same name. Something like the following...…

Kivy: Access configuration values from any widget

Im using kivy to create a small App for computer aided learning.At the moment I have some problems with accessing config values. I get the value withself.language = self.config.get(basicsettings, langu…

Multiprocessing with threading?

when I trying to make my script multi-threading, Ive found out multiprocessing,I wonder if there is a way to make multiprocessing work with threading?cpu 1 -> 3 threads(worker A,B,C) cpu 2 -> 3 …

Pandas Groupby Unique Multiple Columns

I have a dataframe.import pandas as pd df = pd.DataFrame( {number: [0,0,0,1,1,2,2,2,2], id1: [100,100,100,300,400,700,700,800,700], id2: [100,100,200,500,600,700,800,900,1000]})id1 id2 nu…

OpenCV Error: Assertion failed when using COLOR_BGR2GRAY function

Im having a weird issue with opencv. I have no issues when working in a jupyter notebook but do when trying to run this Sublime.The error is: OpenCV Error: Assertion failed (depth == CV_8U || depth == …

matplotlib 1.3.1 has requirement numpy=1.5, but youll have numpy 1.8.0rc1 which is incompatible

Im executing bellow command in Mac (High Sierra) as a part of getting started with pyAudioAnalysis.pip install numpy matplotlib scipy sklearn hmmlearn simplejson eyed3 pydub Im getting following error…

VS Code Debugger Immediately Exits

I use VS Code for a python project but recently whenever I launch the debugger it immediately exits. The debug UI will pop up for half a second then disappear. I cant hit a breakpoint no matter where i…

Sudoku Checker in Python

I am trying to create a sudoku checker in python:ill_formed = [[5,3,4,6,7,8,9,1,2],[6,7,2,1,9,5,3,4,8],[1,9,8,3,4,2,5,6,7],[8,5,9,7,6,1,4,2,3],[4,2,6,8,5,3,7,9], # <---[7,1,3,9,2,4,8,5,6],[9,6,1,5,…