Why does this Python code not print 1 from its superclass __init__?
Why does the following print only "2"? Doesn't it call A's __init__ method? I expected it to print "1" and then "2" since I thought A's __init__ would be called. class A: def __init__(self): print(1) class B(A): def __init__(self): super(A, self).__init__() print(2) obj = B()
6/16/2021 7:40:46 PMJosh Greig
17 AnswersNew Answer
[Part 1 of 3] Excellent question... In scenarios where the default method resolution order (mro) is fine, then the following lines are equivalent and will accomplish what you need: super().__init__() super(B, self).__init__() Albeit, the interface and the official documentation are quite horrible, IMO. (See link:) https://docs.python.org/3/library/functions.html#super Consider the documented interface below: super([type[, object-or-type]]) The first parameter refers to the child type of the base type to use. Give your head a second to recover from the WTF moment of that statement. Essentially, to target base type members, the child type must be specified. The super() function will then resolve members from the inheritance hierarchy beginning with the base type of the first arg. It would be much more intuitive to specify the base type for the first arg.
[Part 2 of 3] Next... I absolutely HATE the name and documentation for the 2nd parameter. ---- "If the second argument is omitted, the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true (this is useful for classmethods)." ---- If I understand this correctly, the 2nd argument specifies the object reference bound to an instance or class reference. More specifically: - Instance methods require an "object instance" (i.e. self or obj) of the type specified in the 1st arg. - Class methods require a subtype (i.e. cls or B) of the type specified in the 1st arg. This leads to another non-intuitive thing about Python... a class can be a subclass of itself. So, issubclass(B, B) would return True. (Weird) - Static methods require omitting the 2nd arg since these are completely stateless and not bound to any reference.
[Part 3 of 3] Therefore, the following examples would be used in their respective contexts: #Targets a base instance constructor. super(B, self).__init__() #Targets some base instance method. super(B, self).instanceMethod() #Targets a base class constructor. super(B, cls).__init__() #Targets some base class method. super(B, cls).classMethod() #Targets some base static method. super(B).staticMethod() NOTE: a static constructor in Python wouldn't make sense due to being completely stateless. Anyway... I hope these responses were helpful. I actually had to explore this myself and I'm just sharing my own assessment. Thanks for asking about such an interesting scenario.
That's because your super() call is incorrect. Change A to B. You want the super to class B (A), not the super to class A (Object).
Vitaly Sokol Brilliant! 👌 So... my assessment regarding use of unbounded super() is invalid. My opinion of HATE for the documentation strengthened. 😂 I wonder what it's purpose is then?
visph My issue is with the brittleness of the super() function signature and the ambiguous documentation regarding unbound super(). Apparently, Guido van Rossum and other Pythonistas have struggled with this very thing. https://www.artima.com/weblogs/viewpost.jsp?thread=236278 ---- "I did ask on the Python 3000 mailing list about removing unbound super object (the title of the thread was let's get rid of unbound super) and this was Guido's reply: 'Thanks for proposing this -- I've been scratching my head wondering what the use of unbound super() would be. :-) I'm fine with killing it -- perhaps someone can do a bit of research to try and find out if there are any real-life uses (apart from various auto-super clones)?' --- Guido van Rossum Unfortunaly as of now unbound super objects are still around in Python 3.0, but you should consider them morally deprecated." ---- Another good reference about this here: https://stackoverflow.com/questions/26788214/super-and-staticmethod-interaction
it's advised to not provide (optional) arguments to super(), as they will be filled with correct values for you ;)
Maybe because super () -> is the same as super (__ class__, <first argument>) and then super().staticMethod equivalent to A.staticMethod ()
visph , Just trying to answer David Carroll how super can call a static method with no arguments, with a simple single parent example 🙂
visph For clarification, I do agree that A.static_method() is the preferred approach. 😉 My questions go well beyond the level of a typical user in this community and focus on understanding the motivations and subtle implications of various language design decisions at a deeper level. I often spend time reviewing PEP discussions and the C source code of the core libraries to validate personal theories and gain deeper insight. I hope this provides some context on the nature of my follow up question. 👌
David Carroll , thanks for your review, I noticed that super(B).staticMethod() is not suitable for calling the static method of the parent class, here is an example: https://code.sololearn.com/cu7GV4cSUgtd/?ref=app
a static method is meaning to be called directly by bound the class itself: there's no reason to use super() to call it, as there's no reason/meaning of overiding it... call to a static method of A should be: A.static_method() from anywhere ^^
Vitaly Sokol also, in this case super().static_method() is equivalent to A.static_method(), but not if you call it from a class not inherited from A, or not really from a class not only inherited from A (in this last case, the function should be searched and called on all parent classes ;P)
Vitaly Sokol yes, but I was meaning caĺling 'super' method with or without arguments (I put parenthesis just to make 'super' more explicitly a callable) ;)
This is super cool. Thanks
I am don't understand coding