How to call super method from grandchild class? - python

I am working with some code that has 3 levels of class inheritance. From the lowest level derived class, what is the syntax for calling a method 2 levels up the hierarchy, e.g. a super.super call? The "middle" class does not implement the method I need to call.

Well, this is one way of doing it:
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def my_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Hello Grandparent"
Grandparent.my_method(self)
Maybe not what you want, but it's the best python has unless I'm mistaken. What you're asking sounds anti-pythonic and you'd have to explain why you're doing it for us to give you the happy python way of doing things.
Another example, maybe what you want (from your comments):
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def some_other_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Hello Grandparent"
super(Child, self).my_method()
As you can see, Parent doesn't implement my_method but Child can still use super to get at the method that Parent "sees", i.e. Grandparent's my_method.

This works for me:
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def my_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Hello Grandparent"
super(Parent, self).my_method()

If you want two levels up, why not just do
class GrandParent(object):
def act(self):
print 'grandpa act'
class Parent(GrandParent):
def act(self):
print 'parent act'
class Child(Parent):
def act(self):
super(Child.__bases__[0], self).act()
print 'child act'
instance = Child()
instance.act()
# Prints out
# >>> grandpa act
# >>> child act
You can add something defensive like checking if __bases__ is empty or looping over it if your middle classes have multiple inheritance. Nesting super doesn't work because the type of super isn't the parent type.

You can do this by following ways
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def my_other_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Inside Child"
super(Child, self).my_method()
In this case Child will call base class my_method but base class my_method is not present there so it will call base class of parent class my_method in this way we can call my_method function of grandparent
Another Way
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def my_other_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Inside Child"
super(Parent, self).my_method()
In this way we are directly calling function base class my_method function of the parent class
Another way but not pythonic way
class Grandparent(object):
def my_method(self):
print "Grandparent"
class Parent(Grandparent):
def my_other_method(self):
print "Parent"
class Child(Parent):
def my_method(self):
print "Inside Child"
Grandparent.my_method()
In this way we are directly calling my_method function by specifying the class name.

Made and tested in python 3
class Vehicle:
# Initializer / Instance Attributes
def __init__(self, name, price):
self.name = name
self.price = price
# instance's methods
def description(self):
print("\nThe car {} has a price of {} eur".format(self.name, self.price))
#Object Vehicle
m3 = Vehicle("BMW M3", 40000)
m3.description()
class Camper(Vehicle):
def __init__(self,nome,prezzo,mq):
super().__init__(nome,prezzo)
self.mq=mq
# instance's methods
def description(self):
super().description()
print("It has a dimension of",format(self.mq)+" mq")
#Camper Object(A camper is also a Vehicle)
marcopolo=Camper("Mercede MarcoPolo",80000,15)
marcopolo.description()
Output:
The car BMW M3 has a price of 40000 eur
The car Mercede MarcoPolo has a price of 80000 eur
It has a dimension of 15 mq

Related

How can I implement a method to print an object in the super class?

When I run this, I get the desired string corresponding to the species object that is created. My goal here is to be able to create a method called speak in the Animal class that achieves the same thing. But I don't have a good understanding on how to do that.
class Animal(object):
def __init__(self):
pass
def speak():
pass
class Mammal(Animal):
def __init__(self):
Animal.__init__(self)
class Cat(Mammal):
def __init__(self):
Mammal.__init__(self)
def __str__(self):
return "meeeow"
class Dog(Mammal):
def __init__(self):
Mammal.__init__(self)
def __str__(self):
return "wooof"
class Primate(Mammal):
def __init__(self):
Mammal.__init__(self)
class Hacker(Primate):
def __init__(self):
Primate.__init__(self)
def __str__(self):
return "Hello world!"
garfield = Cat()
print(garfield)
spike = Dog()
print(spike)
john = Hacker()
print(john)
Yours inherited classes can access any method defined in the parent class. So to achieve this, just define a new method called speak in Animal class and print as you did in your examples:
class Animal(object):
def __init__(self):
print(self)
pass
def speak(self):
print(self)
Then just create the instance and call the function:
garfield = Cat()
garfield.speak()
Output
meeeow
Modify your Animal class like below. When you call the super method from your subclass, you're passing the instance of the class you created to the parent's init function. So the instance of class is passed to the Mammal init function, which calls super and passes the instance to the Animal init function.
class Animal(object):
def __init__(self):
self.speak()
def speak(self):
print(self)

Calling Parent method directly in Python

I have a testmethod in the GParent class which is inherited by Parent and Child..
How can I do that?
I tried this but its not working...
GParent.testmethod(self)
class GParent():
def testmethod(self):
print "This is test method"
class Parent():
def testmethod(self):
print "This is test method"
class Child(Parent):
def __init__(self):
print "This is init method"
GParent.testmethod(self)
c = Child()
first of all: https://docs.python.org/2/tutorial/classes.html#inheritance
At any rate...
GParent.testmethod(self) <-- calling a method before it is defined
class GParent(): <-- always inherit object on your base class to ensure you are using new style classes
def testmethod(self):
print "This is test method"
class Parent(): <-- not inheriting anything
def testmethod(self): <-- if you were inheriting GParent you would be overriding the method that is defined in GParent here.
print "This is test method"
class Child(Parent):
def __init__(self):
print "This is init method"
GParent.testmethod(self) <-- if you want to call the method you are inheriting you would use self.testmethod()
c = Child()
Take a look at this code and run it, maybe it will help you out.
from __future__ import print_function #so we can use python 3 print function
class GParent(object):
def gparent_testmethod(self):
print("Grandparent test method ")
class Parent(GParent):
def parent_testmethod(self): #
print("Parent test method")
class Child(Parent):
def child_testmethod(self):
print("This is the child test method")
c = Child()
c.gparent_testmethod()
c.parent_testmethod()
c.child_testmethod()
You cannot call GParent's testmethod without an instance of GParent as its first argument.
Inheritance
class GParent(object):
def testmethod(self):
print "I'm a grandpa"
class Parent(GParent):
# implicitly inherit __init__()
# inherit and override testmethod()
def testmethod(self):
print "I'm a papa"
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
# You can only call testmethod with an instance of Child
# though technically it is calling the parent's up the chain
self.testmethod()
# inherit parent's testmethod implicitly
c = Child() # print "I'm a papa"
However, two ways of calling a parent's method explicitly is through composition or class method
Composition
class Parent(object):
def testmethod(self):
print "I'm a papa"
class Child(object):
def __init__(self):
self.parent = Parent()
# call own's testmethod
self.testmethod()
# call parent's method
self.parentmethod()
def parentmethod(self):
self.parent.testmethod()
def testmethod(self):
print "I'm a son"
c = Child()
Class method
class Parent(object):
#classmethod
def testmethod(cls):
print "I'm a papa"
class Child(object):
def __init__(self):
# call own's testmethod
self.testmethod()
# call parent's method
Parent.testmethod()
def testmethod(self):
print "I'm a son"
c = Child()
It has become advisory to use composition when dealing with multiple inheritance, since inheritance creates dependency to the parent class.

Call a parent class method from a child class in Python 2

I want to call parent class method using super() in Python 2.
In Python 3, I'd code it like this:
class base:
#classmethod
def func(cls):
print("in base: " + cls.__name__)
class child(base):
#classmethod
def func(cls):
super().func()
print("in child: " + cls.__name__)
child.func()
with this output:
in base: child
in child: child
However, I have no idea, how do this in Python 2. Of course, I can use base.func(), but I don't like to specify parent class name in addition and mainly I get unwanted result:
in base: base
in child: child
With cls (cls is child) as first argument in super() function call, I get this error:
TypeError: must be type, not classobj
Any idea how do it using super() or analogous function in which I don't have to specify name of parent class?
furthering the other answer you can do classmethods for it like
class base(object):
#classmethod
def func(cls):
print("in base: " + cls.__name__)
class child(base):
#classmethod
def func(cls):
super(cls, cls).func()
print("in child: " + cls.__name__)
child.func()
You parent object needs to inherit from object in python 2. So:
class base(object):
def func(self):
print("in base")
class child(base):
def func(self):
super(child, self).func()
print("in child")
c = child()
c.func()
I was trying to do something similar where I was trying to basically "walk up" the inheritance chain until I found a certain base class and then do something there with the class name. The issue I was having was that ALL of these answers assume that you know the name of the class you are trying to get the super of. I tried the "super(cls, cls)" approach but got the "inifinite recursion" issue described above. Here is where I landed
#classmethod
def parent_name(cls):
if BaseDocument in cls.__bases__:
# This will return the name of the first parent that subclasses BaseDocument
return cls.__name__
else:
for klass in cls.__bases__:
try:
parent_name = klass.parent_name()
if parent_name is not None:
return parent_name
except AttributeError:
pass
return None

Pass a parent class as an argument?

Is it possible to leave a parent class unspecified until an instance is created?
e.g. something like this:
class SomeParentClass:
# something
class Child(unspecifiedParentClass):
# something
instance = Child(SomeParentClass)
This obviously does not work. But is it possible to do this somehow?
You can change the class of an instance in the class' __init__() method:
class Child(object):
def __init__(self, baseclass):
self.__class__ = type(self.__class__.__name__,
(baseclass, object),
dict(self.__class__.__dict__))
super(self.__class__, self).__init__()
print 'initializing Child instance'
# continue with Child class' initialization...
class SomeParentClass(object):
def __init__(self):
print 'initializing SomeParentClass instance'
def hello(self):
print 'in SomeParentClass.hello()'
c = Child(SomeParentClass)
c.hello()
Output:
initializing SomeParentClass instance
initializing Child instance
in SomeParentClass.hello()
Have you tried something like this?
class SomeParentClass(object):
# ...
pass
def Child(parent):
class Child(parent):
# ...
pass
return Child()
instance = Child(SomeParentClass)
In Python 2.x, also be sure to include object as the parent class's superclass, to use new-style classes.
You can dynamically change base classes at runtime. Such as:
class SomeParentClass:
# something
class Child():
# something
def change_base_clase(base_class):
return type('Child', (base_class, object), dict(Child.__dict__))()
instance = change_base_clase(SomeParentClass)
For example:
class Base_1:
def hello(self):
print('hello_1')
class Base_2:
def hello(self):
print('hello_2')
class Child:pass
def add_base(base):
return type('Child', (base, object), dict(Child.__dict__))()
# if you want change the Child class, just:
def change_base(base):
global Child
Child = type('Child', (base, object), dict(Child.__dict__))
def main():
c1 = add_base(Base_1)
c2 = add_base(Base_2)
c1.hello()
c2.hello()
main()
Result:
hello_1
hello_2
Works well in both python 2 and 3.
For more information, see the related question How to dynamically change base class of instances at runtime?

python: cleanest way to wrap each method in parent class in a "with"

I have a parent class that has a bunch of class methods:
class Parent():
#classmethod
def methodA(cls):
pass
#classmethod
def methodB(cls):
pass
In my subclass, I would like to wrap a subset of the methods inside a "with". It should achieve this effect:
class Child(Parent):
#classmethod
def methodA(cls):
with db.transaction:
super(Child, cls).methodA()
I have a bunch of methods that follow this pattern and would prefer not to repeat myself. Is there a cleaner way to do this?
It seems you should move the with db.transaction into the base.
Make a method in the base, returning the db.transaction
#staticmethod
def gettransaction(): return db.transaction
then you overload it in the children as/if needed.
In the base you then do
def methodB(cls):
with cls.gettransaction():
bla ...
Here's a complete working example with a dummy transaction
class transact:
def __enter__(a):
print "enter"
def __exit__(a,b,c,d):
print "exit"
class transact2:
def __enter__(a):
print "enter2"
def __exit__(a,b,c,d):
print "exit2"
class Parent():
#staticmethod
def gettrans():
return transact()
def methodA(cl):
with cl.gettrans():
print "A"
class Child(Parent):
pass
#staticmethod
def gettrans():
return transact2()
p=Parent()
p.methodA()
c=Child()
c.methodA()
this results in
enter
A
exit
enter2
A
exit2

Categories