How to call a parent class's function? [duplicate] - python

This question already has answers here:
How do I call a parent class's method from a child class in Python?
(16 answers)
Closed 1 year ago.
I have a parent class with a function. There is a subclass of the parent class that has the same function name, but instead of overriding it as usual, I would like to call the parent's function as well.
Here is an example:
class Person:
def __init__(self,p):
self.p = p
def printp(self):
print(self.p)
class Bob(Person):
def printp(self):
print('letter')
b = Bob('p')
b.printp()
Currently, this prints 'p'. I would like it to print:
p
letter

This could be one solution:
class Person:
def __init__(self,p):
self.p = p
def printp(self):
print(self.p)
class Bob(Person):
def printp(self):
# here I use super to call parent class printp()
super().printp()
print('letter')
b = Bob('p')
b.printp()
Output:
p
letter

You can call the parent's method from the child's method like so:
class Bob(Person):
def printp(self):
super().printp()
print('letter')

Related

Is it possible to call parent class-private methods from child class in Python? [duplicate]

This question already has answers here:
Getting parent private or protected values from the child class
(2 answers)
Closed 8 months ago.
I'm trying to call __search from parent class A in child class B but I get the error:
AttributeError: 'B' object has no attribute '_B__search'
This seems to be only happening for methods starting with __. Is there a way to call these class-private methods when doing inheritance?
class A:
def __init__(self, a):
self.a = a
def __search(self):
return self.a
def display(self):
print(self.a)
class B(A):
def display(self):
res = self.__search()
return res
cB = B(2)
cB.display()
Yes, but it's terrible practice.
In Python, a method whose name begins with __ and does not end with it (so magic methods like __add__ are excluded) is obfuscated with the class name. That is,
class A:
def __foo(self):
return 1
is equivalent to
class A:
def _A__foo(self):
return 1
So if you really want to call __search defined on A, you should write
res = self._A__search()
Again, this is bad practice. Methods starting with __ are obfuscated because that's the Python convention for private functions, so they shouldn't be called from outside the class or in subclasses. You mention in the comments that this is a temporary fix, so that's understandable, but I do hope it's not intended to stay this way for very long.
An attribute name beginning with __ is private, and mangled to _classname__attribute. You need to call it by the mangled name.
class B(A):
def display(self):
res = self._A__search()
return res

Inheritance method overwrite in some conditions [duplicate]

When creating a simple object hierarchy in Python, I'd like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this (super). In Perl, I might do this:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
#ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
In Python, it appears that I have to name the parent class explicitly from the child.
In the example above, I'd have to do something like Foo::frotz().
This doesn't seem right since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created.
Is this an actual limitation in python, a gap in my understanding or both?
Use the super() function:
class Foo(Bar):
def baz(self, **kwargs):
return super().baz(**kwargs)
For Python < 3, you must explicitly opt in to using new-style classes and use:
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
Python also has super as well:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
Example:
class A(object): # deriving from 'object' declares A as a 'new-style-class'
def foo(self):
print "foo"
class B(A):
def foo(self):
super(B, self).foo() # calls 'A.foo()'
myB = B()
myB.foo()
ImmediateParentClass.frotz(self)
will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up whatever in AnyClass's ancestors if AnyClass doesn't define/override it, and this holds true for "child class calling parent's method" as for any other occurrence!
Python 3 has a different and simpler syntax for calling parent method.
If Foo class inherits from Bar, then from Bar.__init__ can be invoked from Foo via super().__init__():
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
Many answers have explained how to call a method from the parent which has been overridden in the child.
However
"how do you call a parent class's method from child class?"
could also just mean:
"how do you call inherited methods?"
You can call methods inherited from a parent class just as if they were methods of the child class, as long as they haven't been overwritten.
e.g. in python 3:
class A():
def bar(self, string):
print("Hi, I'm bar, inherited from A"+string)
class B(A):
def baz(self):
self.bar(" - called by baz in B")
B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"
yes, this may be fairly obvious, but I feel that without pointing this out people may leave this thread with the impression you have to jump through ridiculous hoops just to access inherited methods in python. Especially as this question rates highly in searches for "how to access a parent class's method in Python", and the OP is written from the perspective of someone new to python.
I found:
https://docs.python.org/3/tutorial/classes.html#inheritance
to be useful in understanding how you access inherited methods.
Here is an example of using super():
#New-style classes inherit from object, or from another new-style class
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self):
self.moves.append('walk')
self.moves.append('run')
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super(Superdog, self).moves_setup()
self.moves.append('fly')
dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly'].
#As you can see our Superdog has all moves defined in the base Dog class
There's a super() in Python too. It's a bit wonky, because of Python's old- and new-style classes, but is quite commonly used e.g. in constructors:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
I would recommend using CLASS.__bases__
something like this
class A:
def __init__(self):
print "I am Class %s"%self.__class__.__name__
for parentClass in self.__class__.__bases__:
print " I am inherited from:",parentClass.__name__
#parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()
If you don't know how many arguments you might get, and want to pass them all through to the child as well:
class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)
(From: Python - Cleanest way to override __init__ where an optional kwarg must be used after the super() call?)
There is a super() in python also.
Example for how a super class method is called from a sub class method
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self,x):
self.moves.append('walk')
self.moves.append('run')
self.moves.append(x)
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super().moves_setup("hello world")
self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves())
This example is similar to the one explained above.However there is one difference that super doesn't have any arguments passed to it.This above code is executable in python 3.4 version.
In this example cafec_param is a base class (parent class) and abc is a child class. abc calls the AWC method in the base class.
class cafec_param:
def __init__(self,precip,pe,awc,nmonths):
self.precip = precip
self.pe = pe
self.awc = awc
self.nmonths = nmonths
def AWC(self):
if self.awc<254:
Ss = self.awc
Su = 0
self.Ss=Ss
else:
Ss = 254; Su = self.awc-254
self.Ss=Ss + Su
AWC = Ss + Su
return self.Ss
def test(self):
return self.Ss
#return self.Ss*4
class abc(cafec_param):
def rr(self):
return self.AWC()
ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())
Output
56
56
56
In Python 2, I didn't have a lot luck with super(). I used the answer from
jimifiki on this SO thread how to refer to a parent method in python?.
Then, I added my own little twist to it, which I think is an improvement in usability (Especially if you have long class names).
Define the base class in one module:
# myA.py
class A():
def foo( self ):
print "foo"
Then import the class into another modules as parent:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
class department:
campus_name="attock"
def printer(self):
print(self.campus_name)
class CS_dept(department):
def overr_CS(self):
department.printer(self)
print("i am child class1")
c=CS_dept()
c.overr_CS()
If you want to call the method of any class, you can simply call Class.method on any instance of the class. If your inheritance is relatively clean, this will work on instances of a child class too:
class Foo:
def __init__(self, var):
self.var = var
def baz(self):
return self.var
class Bar(Foo):
pass
bar = Bar(1)
assert Foo.baz(bar) == 1
class a(object):
def my_hello(self):
print "hello ravi"
class b(a):
def my_hello(self):
super(b,self).my_hello()
print "hi"
obj = b()
obj.my_hello()
This is a more abstract method:
super(self.__class__,self).baz(arg)

Why are instances of this class being overwritten? [duplicate]

This question already has answers here:
Meaning of #classmethod and #staticmethod for beginner [duplicate]
(12 answers)
Closed 6 years ago.
I'm programming a script with Python using instances of FileHandler class but the second overwrites the first even without being assigned to the same variables.
The class:
class FileHandler():
name = None
path = None
#classmethod
def __init__(self,name,path):
self.name=name
self.path=path
#classmethod
def getName(self):
return self.name
#classmethod
def getPath(self):
return self.path
The script:
import fileHandler
origen=fileHandler.FileHandler('a','b')
destino=fileHandler.FileHandler('c','d')
print origen.getName(),origen.getPath()
print destino.getName(),destino.getPath()
The result:
c d
c d
You are using __init__ method as a class method.
Using #classmethod for every method will result in a singleton, that's why the vars overwrite.

Have a class to initialise an object from a different class [duplicate]

This question already has an answer here:
How to create child class instance using some magic in parent __new__?
(1 answer)
Closed 6 years ago.
Currently, I have a #classmethod that returns the right class given a variable. It looks something like:
class Parent():
#classmethod
def GetInstance(cls, variable):
if variable == 'foo':
return Child()
class Child(Parent):
def Something(self):
pass
instance = Parent.GetInstance('foo')
result = instance.Something()
I prefer not to define and use GetInstance. Instead, I would like the Main() to simply be:
instance = Parent('foo')
result = instance.Something()
While keeping all the benefits of the structure above. I want class Parent() to return an object of class Child() when called, without the need of using a method. __init__ unfortunately does not seem to help, as it cannot return anything. Any ideas?
Just override 'new' special method. It's 'new' method which is responsible for calling creating an instance, allocating memory and then initialize it by calling 'init' . To be specific
new is static class method, while init is instance method. new has to create the instance first, so init can initialize it. Note that init takes self as parameter. Until you create instance there is no self.
EDIT Ok, I went back and fixed it. Totally hackey and very brittle. I hope you don't want to keep extending this. I put this here as illustrative of why this is a bad idea.
Here is a sketch of how you could accomplish this. But please, just use a factory method.
>>> class Parent(object):
... def __new__(typ, *args, **kwargs):
... if args and args[0] == 'foo':
... return Child()
... else:
... return super(Parent, typ).__new__(typ)
...
>>> class Child(Parent):
... __new__ = object.__new__
...
>>> a = Parent('foo')
>>> a
<__main__.Child object at 0x1023275f8>
>>> p = Parent()
>>> p
<__main__.Parent object at 0x1023275c0>
>>>
Add a list of children[] in your parent class:
class Parent():
def __init__(self):
children = list()
That way you can create a child() object and then append it by doing:
child - Child() # create new child obj
parent.children.append(child)
Then it should be simple to get a child from the list of children that you want using a loop etc.

passing class arguments defined in parent class from child class inheriting the parent [duplicate]

This question already has answers here:
How do I call a parent class's method from a child class in Python?
(16 answers)
Closed 6 years ago.
I am pretty new to OOP in python (ver. 3.5). I created a generic class and I would like to create a new one inheriting from it.
My parent class (say A) has two args defined within its __init__() method. How can I inherit those in my child class (say B) so that when I instantiate B I can pass it the args I would pass to A? I am actually trying to use the super() function, but I am not quite sure about the result.
I tried the below, but it gives me TypeError: __init__() takes 1 positional argument but 3 were given
class A(): # parent class
def __init__(self, x, y):
self.x = x
self.y = y
class B(A): # child class
def __init__(self):
super().__init__(x, y)
And then I would do (e.g.) b = B(5, 5)
EDIT 1
As my question was identified as duplicate of this answer, I would lke to state why it is different and why that answer did not help me to solve my problem:
I am not asking about how to access the parameters of a parent class from a child class, but if it was possible to instantiate a class with a parent class inherited, passing to it the arguments like if it was a call to the parent's class.
The answer is "I can't", unless I define again the same arguments in the child class __init__() method. Finally, as I said I am new to OOP, the indicated answer was not helpful, as the initial question was too difficult to understand to me (and it's not even in python).
class A(): # parent class
def __init__(self, x, y):
self.x = x
self.y = y
class B(A): # child class
def __init__(self, x, y):
A.__init__(self, x, y)
So now you can use b = B(5, 5)

Categories

Resources