MyTetra Share
Делитесь знаниями!
Chain-calling parent constructors in python
Время создания: 16.07.2018 10:18
Текстовые метки: python oop parent constructor super
Раздел: Python
Запись: Velonski/mytetra-database/master/base/1531718311x8yf9aoijr/text.html на raw.githubusercontent.com

Consider this - a base class A, class B inheriting from A, class C inheriting from B. What is a generic way to call a parent class constructor in a constructor? If this still sounds too vague, here's some code.


class A(object):

def __init__(self):

print "Constructor A was called"


class B(A):

def __init__(self):

super(B,self).__init__()

print "Constructor B was called"


class C(B):

def __init__(self):

super(C,self).__init__()

print "Constructor C was called"


c = C()

This is how I do it now. But it still seems a bit too non-generic - you still must pass a correct type by hand.


Now, I've tried using self.__class__ as a first argument to super(), but, obviously it doesn't work - if you put it in the constructor for C - fair enough, B's constructor gets called. If you do the same in B, "self" still points to an instance of C so you end up calling B's constructor again (this ends in an infinite recursion).


There is no need to think about diamond inheritance for now, I am just interested in solving this specific problem.


python oop inheritance constructor

shareimprove this question

asked May 24 '09 at 15:54


shylent

6,67452849

marked as duplicate by PM 2Ring python Nov 12 '16 at 18:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


"But it still seems a bit too non-generic - you still must pass a correct type by hand."?? You're passing the class name to super(). You never need to know the superclass or anything else. How is this non-generic? What problem does it create? Can you give an example where this breaks? – S.Lott May 24 '09 at 17:08

3

I am not ready to answer this question if full. But anyway, what if the class gets renamed? What if I want to write a decorator function to automate this kind of chaining? Now I see, that this is not possible, but at the time of asking the question I did not know that. – shylent May 24 '09 at 17:27

add a comment

3 Answers

active oldest votes

up vote

158

down vote

accepted

The way you are doing it is indeed the recommended one (for Python 2.x).


The issue of whether the class is passed explicitly to super is a matter of style rather than functionality. Passing the class to super fits in with Python's philosophy of "explicit is better than implicit".


shareimprove this answer

answered May 24 '09 at 16:12


dF.

49.6k22107130

3

I've had a really hard time deciding which answer to accept, but I will accept this one, simply because it is relevant to the version of python I am using. – shylent May 24 '09 at 19:51

9

In Python 2.6 I get TypeError: super() argument 1 must be type, not classobj using this method. Am I missing something? – Leopd May 26 '10 at 23:30

12

@Leopd: super() only works with new-style classes, i.e. you must inherit from object. – dF. May 28 '10 at 20:25

19

Python IS a strongly typed language, but it is dynamically typed. There is a difference between weak and dynamic typing. – Josh Smeaton Dec 19 '10 at 11:45

2

@TheScienceBoy the definitions are clear though. Python is strong-dynamic. Something like Java is strong-static. PHP is weak-dynamic. Static typing guarantees (within some limits at least) that input parameters are the correct type. Strong typing means that the compiler/runtime will not attempt to coerce the value of one type to another.. like changing "1" to a 1 so you can do math on it. Please see here: wiki.python.org/moin/… – Josh Smeaton Jul 26 '15 at 23:23

show 4 more comments

up vote

168

down vote

Python 3 includes an improved super() which allows use like this:


super().__init__(args)

shareimprove this answer

answered May 24 '09 at 16:13


ironfroggy

5,99032538

1

if I have more than one parent class how will super identify the which parent class to invoke ? – Kracekumar Aug 13 '11 at 20:02

2

@kracekumar It will be determined by the class' Method Resolution Order (MRO), which you can find out by calling MyClassName.mro(). I may be incorrect, but I believe that the first specified parent is the one whose __init__ will be called. – Cam Jackson Aug 16 '11 at 2:14

@ironfroggy, would you mind elaborating on How does this improved super help with the question? I just found this old thread and I am having the same exact questions. Also Have things improved for Python 2.x since this question was first asked? – Amelio Vazquez-Reina Apr 4 '13 at 16:53

@user815423426 Because it makes the up-calls more generic, no longer repeating the class name, which was the subject of the original question. – ironfroggy Sep 15 '13 at 18:17

@kracekumar, super(X,obj) actually returns a special "super" object that, when you do an attribute access on it, will return the attribute that would have been returned had class X had no attributes at all. for example, super(X,obj).__init__ will return the init method of your obj as if init in class X not been there. Now, if class X has two parents, and X.__init__ doesnt exist, the default behavior is to call init of only one of the parents, not both. This is effectively what super is doing... giving you one of the parents. – Chris Cogdon Mar 25 '15 at 19:21

add a comment

up vote

21

down vote

You can simply write :


class A(object):


def __init__(self):

print "Constructor A was called"


class B(A):


def __init__(self):

A.__init__(self)

# A.__init__(self,<parameters>) if you want to call with parameters

print "Constructor B was called"


class C(B):


def __init__(self):

# A.__init__(self) # if you want to call most super class...

B.__init__(self)

print "Constructor C was called"

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования