This question already has an answer here:
Why not constructor of super class invoked when we declare the object of sub class?
(1 answer)
Closed 9 years ago.
class A:
def __init__(self):
print 'A'
class B(A):
def __init__(self):
print 'B'
b = B()
B
In C++, I would have expected to see A B output, but in Python I am getting only B. I know that I can do super(B, self).__init__() to achieve the same in Python, but as this is apparently not the default (or is it - I am new to the syntax as well), I am worried that the paradigms for instatinating objects are completely different.
So what are objects in Python, what is their relation with classes and what is the standard way to initialize all data in all parent classes in Python?
Python rarely does anything automatically. As you say, if you want to invoke the superclass __init__, then you need to do it yourself, usually by calling super:
class B(A):
def __init__(self):
print 'B'
super(B, self).__init__()
The point to note is that instance attributes, like everything else in Python, are dynamic. __init__ is not the constructor, that's __new__ which you rarely need to meddle with. The object is fully constructed by the time __init__ is called, but since instance attributes are dynamic they are usually added by that method, which is only special in that it's called first once the object is created.
You can of course create instance attributes in any other method, or even from outside the class itself by simply doing something like myBobj.foo = 'bar'.
So what are objects in Python
Well, objects in python are like dictionaries of members and methods. It's no more sophisticated than that. You don't have visibility handling (if you want to hide a member, just do not talk about it in the public documentation, only with a comment).
what is their relation with classes
A class defines the method/member skeleton that will instantiate that dict/object. So you got the constructor __init__(), which is only a handler used when you create that object.
what is the standard way to initialize all data in all parent classes in Python?
Either you do not redefine the constructor, and then all parent classes will have their constructor initiated (like the default C++ behavior) or you do redefine the constructor, and then have to make an explicit call to your parent class's constructor.
Remember the zen of python: "Explicit is better than implicit". It totally applies here.
You need to invoke the base constructor in your inherited class constructor:
class B(A):
def __init__(self):
A.__init__(self)
# super(B, self).__init__() you can use this line as well
print 'B'
Related
in the below example I want to know when I should use one of them for inherits? I think both are valid so, why sometimes I have to use super if the other way is workable to work with?
class User:
def __init__(self):
self._user = "User A"
pass
class UserA(User):
_user = "User B"
def __init__(self):
super().__init__()
class UserB(User):
pass
You are correct, both are valid. The difference is:
UserA: you are overwriting the __init__ method of the ancestor. This is practical if you want to add something during the initialization process. However, you still want to initialize the ancestor, and this can be done via super().__init__(), despite having overwritten the __init__ method.
UserB: you are fully using the __init__ of the ancestor you are inheriting from (by not overwriting the __init__ method). This can be used if nothing extra needs to be done during initialization.
The super() builtin returns a proxy object (temporary object of the superclass) that allows us to access methods of the base class. For example:
class Mammal(object):
def __init__(self, mammalName):
print(mammalName, 'is a warm-blooded animal.')
class Dog(Mammal):
def __init__(self):
print('Dog has four legs.')
super().__init__('Dog')
self represents the instance of the class. By using the “self” keyword we can access the attributes and methods of the class in python
I have came around this question during an interview:
class Parent(object):
def A(self):
print "in A"
class Child(Parent):
def A(self):
print "in B"
C=Child()
Question come here:
is there any way i can call Parent class function A with child object only at instance level without doing any changes in classes?
have searched many question but didn't find any satisfactory answer.Please reply.
Thanks.
Call the method on the class explicitly.
Parent.A(C)
You can use super() builtin.
>>> super(Child, C).A()
in A
It is usually used to call super class implementation inside subclasses, but it is also allowed outside. Docs state:
Also note that super() is not limited to use inside methods. The two
argument form specifies the arguments exactly and makes the
appropriate references.
As you see, methods of objects always have the self parameter.
You can call objects methods as
C.A()
or equivalently, by explicitly passing the self parameter, as:
Child.A(C)
In the second way, you can call also the method of the parent class using the C instance:
Parent.A(C)
If you are looking for a general method to solve this (i.e. without knowing the name of the parent class), you can use super() and type():
super(type(C)).A(C)
However, super() has a nice additional argument to specify an object instance, so you could write also:
super(type(C), C).A()
Use a super call passing the type of child class and the desired instance object which is just C:
super(type(C), C).A() # of the form super(class, obj) where class == Child and obj == C
Having instance C we could get its base class and call its A():
C.__class__.__base__().A()
Below is two versions of my code:
Non-working one
class A:
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
This raises exception:
super(C, self).__init__()
TypeError: must be type, not classobj
Working version
class A(object):
def __init__(self):
print "I am A "
class B:
def __init__(self):
print "I am B "
class C(A, B):
def __init__(self):
super(C, self).__init__()
c = C()
If one of the parent class has inherited object explicitly , there is no exception and things works as desired. Any explanation, why?
With the above working one , it prints "I am A" but not "I am B" which means it initializes only Class A and not Class B. HOw to initialize multiple parent classes in children class?
That's because super only works with new-style classes (that inherit from object). In Python 2, classes where object is nowhere in the inheritance hierarchy (like your first example) are called old-style classes, and should never be used anywhere.
It's an old historical artifact from when Python first got OO added to it, and the developers got it wrong. Among other things, new-style classes allow for the use of super, the descriptor protocol (properties), and makes several fixes to the way multiple inheritance is handled. super is one of them, but the most important is the way method resolution order is computed for diamond inheritance cases (A inherits from B and C which both inherit from D). Read more about it here: http://python-history.blogspot.fr/2010/06/method-resolution-order.html
Note that Python 3 ditched old-style classes entirely, and thus in Python 3 all classes are new-style classes and inherit from object, regardless of whether or not they do it explicitly.
super() only works for new-style classes(Any class which inherits from object).So You couldn't pass class object to super.
There are two typical use cases for super. In a class hierarchy with single inheritance, super can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the use of super in other programming languages.
The second use case is to support cooperative multiple inheritance in a dynamic execution environment. This use case is unique to Python and is not found in statically compiled languages or languages that only support single inheritance. This makes it possible to implement “diamond diagrams” where multiple base classes implement the same method. Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).
a typical superclass call looks like this:
class C(B):
def method(self, arg):
super(C, self).method(arg)
This question already has answers here:
Python - calling ancestor methods when multiple inheritance is involved
(2 answers)
Closed 8 years ago.
Consider:
class X:
def some_method(self):
print("X.some_method called")
class Y:
def some_method(self):
print("Y.some_method called")
class Foo(X,Y):
def some_method(self):
super().some_method()
# plus some Foo-specific work to be done here
foo_instance = Foo()
foo_instance.some_method()
Output:
X.some_method called
Switching the class declaration of Foo to instead be:
class Foo(Y,X):
Alters the output to:
Y.some_method called
If I want both ancestor methods to be called I could alter Foo's implementation as:
def some_method(self):
X().some_method()
Y().some_method()
# plus some Foo-specific work to be done here
This leads to my question. Is there any uber secret way to cause Python to invoke the method on all ancestors without me doing so explicitly like the code, such as (I'm making up the all_ancestors keyword here - does such a thing actually exist?):
def some_method(self):
all_ancestors().some_method()
# plus some Foo-specific work to be done here
with an expected output of:
X.some_method called
Y.some_method called
No, there is no secret way to do that. As I mentioned in your other question, the usual way to do this is not to call all ancestor methods from the single descendant class. Instead, each class should use super to call just one ancestor method, namely the next one up the inheritance chain. If every class in the tree does this (except the topmost base class), then all methods will get called in order. In other words, Foo should use super(), which will call X's method; and then X should also use super(), which will call Y's method.
To make this work right, it is usually best to have a single topmost class in the inheritance tree. In your example this would be a class that is the base of both X and Y. You need such a class to serve as a final stop to the sequence of super calling; this base class should not call super. If you just keep calling super everywhere, eventually it will try to call up to the base object class, and then fail because object doesn't provide the method you're trying to call.
If you can provide X & Y with a common base class or mix-in, this should work:
class ISomeMethod:
def some_method(self):
pass
class X(ISomeMethod):
def some_method(self):
print("X.some_method called")
super(X, self).some_method()
class Y(ISomeMethod):
def some_method(self):
print("Y.some_method called")
super(Y, self).some_method()
some_method should then be called in the order which you declare the base classes in Foo.
I'm trying to do something I consider pretty ordinary in Object Oriented programming
but can't find any documentation on it for Python 2.7
I want to create a subclass of a superclass where, when I'm done
superclass
is bound to the superclass
superclass.subclass is bound to the subclass and
subclass is bound to nothing.
Here's the best solution I can come up with:
class superclass:
pass
class subclass(superclass):
pass
superclass.subclass = subclass
del subclass
Sometimes I want subclass to be in its own file, other times not.
Is there a more elgant solution where I don't have to manually perform the
last two lines?
Although
class superclass:
class subclass:
pass
almost does the right thing, subclass doesn't actually inherit from superclass.
And if I try to do:
class superclass:
class subclass(superclass):
pass
I get an error message that superclass is unbound.
I agree with everyone else that this is a silly thing to do and I don't think you should do it, but in the interest of knowledge:
class Superclass(object):
pass
Superclass.Subclass = type('Subclass', (Superclass,), {
'foo': lambda self: self,
})
where the dictionary argument contains any methods. I don't think there's a nice way to do this with the class syntax, but that's really just syntactic sugar for calling type anyway.
You don't have to define the methods as lambdas; they can be normal functions with def as long as they have the self argument. You'll probably want to hide their definitions if you do that, though....
Here's a simple class decorator to do the referencing:
def refer(cls):
cls.__bases__[0].subclass = cls
return cls
Here's how you use it:
>>> class Superclass:
pass
>>> #refer
class Subclass(SuperClass):
pass
You will still need to delete Subclass if you don't want the name in the module namespace.