1

As far as I understand, in Python methods of parent class are overridden. So all class methods are virtual by default as can be seen from the code below.

class Parent(object):

    def Method1(self):
        print 'FOO'

class Child(Parent):

    def Method1(self):
        print 'BAR'

myInstance = Child()

#Overridden method is called
myInstance.Method1()                             # BAR

#Is it possible to do the following?
myInstance.{something}                           # FOO

QUESTIONS:

  • Is it possible to call parent method Parent.Method1() from the instance myInstance of the child class?

  • Is it possible to make def Parent.Method1(self) not to be overridden by a method with the same name, but some different set of arguments def Child.Method1(self,x,y)?

Konstantin
  • 2,937
  • 10
  • 41
  • 58

3 Answers3

2

You call parent methods by having the super() function search for the next method in the MRO (method resolution order):

class Child(BaseClass):
    def Method1(self):
        print 'BAR'
        super(Child, self).Method1()  # will call BaseClass.Method1

where self is the instance reference, so super(type(myInstance), myInstance).Method1() would achieve the same thing from outside the method.

Or you can access the unbound method on the class, and pass in the instance explicitly; you'd be able to do this outside the method too:

BaseClass.Method1(myInstance)

because now you referenced the method attribute directly on the class instead, and passed in the instance as an explicit self to that method; you'd use self from inside a method on Child there.

Python attributes (methods are attributes too) are looked up by name and such look-ups search through the instance, then the class of the instance, then through each parent class until a match is found; the signature of a method doesn't come into play here.

You can still override a method in a child class, change the signature, but remain compatible with the parent method by using keyword arguments:

class Child(BaseClass):
    def Method1(self, x=None, y=None):
        if x is None and y is None:
            # arguments left at defaults, call base method
            return super(Child, self).Method1()

        print 'BAR: {} and {}'.format(x, y)

Now if you call myInstance.Method1(), with no arguments, the BaseClass.Method1() method is called, pass in arguments and something else happens instead.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Yes, that's clear for me. I can't figure out on how to call parent method from the instance of the child class, so I may select what to call (child or parent method) in my program – Konstantin Apr 09 '14 at 17:37
  • @Konstantin: That is just what his code shows you how do to. – BrenBarn Apr 09 '14 at 17:38
  • @BrenBarn, I'm not sure. That's calling of the parent method from the child class method using `super()`, no problem with it. I wanted to know is there any way for the Child's instance to invoke either its method or the method of its parent that was overriden – Konstantin Apr 09 '14 at 17:42
  • 1
    @Konstantin: Can you give an example of what you mean? You can call the parent method using `super(Child, child_instance).Method1()` just the same as it's done inside a method. I'm not sure what you mean by calling the method "from the child instance" rather than "from the child class method". – BrenBarn Apr 09 '14 at 17:49
1

Is it possible to call parent method Parent.Method1() from the instance myInstance of the child class?

You can call the method directly, and pass your instance as first argument:

>>> class A(object):
...     def foo(self):
...         print 'foo'
...
>>> class B(A):
...     def foo(self):
...         print 'bar'
...
>>> b = B()
>>> A.foo(b)
foo

Is it possible to make def Parent.Method1(self) not to be overridden by a method with the same name, but some different set of arguments def Child.Method1(self,x,y)?

Yes, you use super and call the parent's method directly:

>>> class A(object):
...     def foo(self, bar='bar'):
...         print bar
...
>>> class B(A):
...     def foo(self):
...         super(B, self).foo(bar='foo')
...
>>> B().foo()
foo
>>> A().foo()
bar
Community
  • 1
  • 1
Esteban Küber
  • 36,388
  • 15
  • 79
  • 97
  • thank you for the reply. Is it possible to do something like B().foo() -> calls parent method, B().foo(x,y) -> calls child method? So argument set prevents virtual function from being overridden. – Konstantin Apr 09 '14 at 18:01
  • 1
    Kind of. The child could define `foo` as `def foo(self, arg1=None, arg2=None)`, and if `arg1` and `arg2` are both `None` in the body, then call the parent method. The child method is always called, but *it* can then decide to call the parent method. In general, Python does not look at the arguments passed to a method to determine which function to actually call. (Which I see now is exactly what Martijn Pieters proposes in his answer.) – chepner Apr 09 '14 at 18:11
1

In addition to using super, there are a couple of explicit options that bypass the MRO:

# Explicitly call Baseclass.Method1, passing your instance as the argument
BaseClass.Method1(myInstance)

# Call Method1 on the (first) base class of the instance.
# This is ugly; don't actually write code like this
# x.__class__.__bases__[0] is just another way to get a reference
# to BaseClass; otherwise, this is identical to the previous option,
# hence the need to repeat myInstance
myInstance.__class__.__bases__[0].Method1(myInstance)
chepner
  • 497,756
  • 71
  • 530
  • 681