python super calling child methods

2024/10/5 17:16:22

There are numerous questions on the usage of super() but none of them appears to answer my question.

When calling super().__init__() from a subclass, all method calls in the super-constructor are actually taken from the subclass. Consider the following class structure:

class A(object):def __init__(self):print("initializing A")self.a()def a(self):print("A.a()")class B(A):def __init__(self):super().__init__()# add stuff for Bself.bnum=3 # required by B.a()        def a(self):print("B.a(), bnum=%i"%self.bnum)b=B()

which fails with

initializing A
Traceback (most recent call last):File "classmagic.py", line 17, in b=B()File "classmagic.py", line 11, in __init__super().__init__()File "classmagic.py", line 5, in __init__self.a()File "classmagic.py", line 15, in aprint("B.a(), bnum=%i"%self.bnum)
AttributeError: 'B' object has no attribute 'bnum'

Here I call the super constructor in B() to initialize some basic structure (some of which is executed as an own function a()). However, if I override the a() function as well, this implementation is used when calling A's constructor which fails because A knows nothing about B and may use different internal variables.

This may or may not be intuitive, but what do I have to do when I want all methods in A only to have access to the functions implemented there?

Answer

If your code has to call specific private methods that cannot be overridden, use a name that starts with two underscores:

class A(object):def __init__(self):print("initializing A")self.__a()def __a(self):print("A.a()")class B(A):def __init__(self):super().__init__()# add stuff for Bself.bnum=3 # required by B.a()        def __a(self):print("B.__a(), bnum=%i"%self.bnum)

Python "mangles" such method names by adding in the class name (plus an underscore) to minimize the chances subclasses overwrite them with their own versions.

The PEP 8 Python Style Guide has this to say about private name mangling:

If your class is intended to be subclassed, and you have attributesthat you do not want subclasses to use, consider naming them withdouble leading underscores and no trailing underscores. This invokesPython's name mangling algorithm, where the name of the class ismangled into the attribute name. This helps avoid attribute namecollisions should subclasses inadvertently contain attributes with thesame name.

Note 1: Note that only the simple class name is used in the mangledname, so if a subclass chooses both the same class name and attributename, you can still get name collisions.

Note 2: Name mangling can make certain uses, such as debugging and__getattr__(), less convenient. However the name mangling algorithmis well documented and easy to perform manually.

Note 3: Not everyone likes name mangling. Try to balance the need toavoid accidental name clashes with potential use by advanced callers.

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

Related Q&A

How to create space between subplots? [duplicate]

This question already has answers here:Manipulation on vertical space in matplotlib subplots(3 answers)Closed 2 years ago.The title pretty much says it all. I have a notebook containing two subplots an…

How to (re)name an empty column header in a pandas dataframe without exporting to csv

I have a pandas dataframe df1 with an index column and an unnamed series of values. I want to assign a name to the unnamed series. The only way to do this that I know so far is to export to df1.csv usi…

Capturing the video stream from a website into a file

For my image classification project I need to collect classified images, and for me a good source would be different webcams around the world streaming video in the internet. Like this one:https://www.…

Recreating time series data using FFT results without using ifft

I analyzed the sunspots.dat data (below) using fft which is a classic example in this area. I obtained results from fft in real and imaginery parts. Then I tried to use these coefficients (first 20) to…

python BeautifulSoup get all href in Children of div

I am new to python and Ive been trying to get links and inner text from this html code : <div class="someclass"><ul class="listing"><li><a href="http://lin…

Python TypeError: sort() takes no positional arguments

I try to write a small class and want to sort the items based on the weight. The code is provided, class Bird:def __init__(self, weight):# __weight for the private variableself.__weight = weightdef wei…

Trouble with basemap subplots

I need to make a plot with n number of basemap subplots. But when I am doing this the all the values are plotted on the first subplot.My data is a set of n matrixes, stored in data_all.f, map = plt.sub…

Remove circular references in dicts, lists, tuples

I have this following really hack code which removes circular references from any kind of data structure built out of dict, tuple and list objects.import astdef remove_circular_refs(o):return ast.liter…

how to change image format when uploading image in django?

When a user uploads an image from the Django admin panel, I want to change the image format to .webp. I have overridden the save method of the model. Webp file is generated in the media/banner folder b…

Write info about nodes to a CSV file on the controller (the local)

I have written an Ansible playbook that returns some information from various sources. One of the variables I am saving during a task is the number of records in a certain MySQL database table. I can p…