zXu
zXu

Reputation: 31

Avoid using child method in parent class in python

Suppose I have two classes in Python as below:

class Parent(object):
    def __init__(self):
        self.num = 0

    def fun1(self):
        print 'p.fun1'

    def fun2(self):
        self.fun1()
        print 'p.fun2'

and

from parent import Parent

class Child(Parent):
    def __init__(self):
        super(Child,self).__init__()

    def fun1(self):
        print 'c.fun1'

    def fun2(self):
        super(Child, self).fun2()
        print 'c.fun2'

and if I call fun2 of Child

from child import Child

test = Child()
test.fun2()

I get output:

c.fun1
p.fun2
c.fun2

Which means the call of Child.fun2() leads to Parent.fun2(). But inside the Parent.fun2(), I use self.fun1() which in this case interpreted as Child.fun1() in my test.

But I really want the class Parent to be individual and the call of Parent.fun2() always uses Parent.fun1() inside it.

How can I avoid this?

I only know that I can make Parent.fun1() private into Parent.__fun1(). But I also have some instances of Parent where I need to use Parent.fun1() outside this class. That means I really need to override the fun1().

Upvotes: 2

Views: 2174

Answers (2)

trib3_IRO
trib3_IRO

Reputation: 11

There is a mechanism called Name Mangling:

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class. Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls Python Classes Documentation

This should work:

class Parent(object):
    def __init__(self):
    self.num = 0

    def fun1(self):
        print 'p.fun1'

    def fun2(self):
        self.__fun1()
        print 'p.fun2'

    __fun1 = fun1

Upvotes: 1

0xc0de
0xc0de

Reputation: 8287

That's how inheritance is supposed to work. For the behavior you need, you might want to reconsider Parent & Child class's relationship, or change the method names or at least make the Parent methods classmethods or staticmethods.

This should work for your need, but I don't really like it.

class Parent(object):
    def __init__(self):
        self.num=0
    def fun1(self):
        print 'p.fun1'
    def fun2(self):
        Parent.fun1(self)
        print 'p.fun2'

Child class can remain the same.

In all classes accessed in the inheritance chain, self will always point to the instance of class actually instantiated and not the current class accessed in super call (or in order to find method/attribute for that matter). So self.fun2 will always point to the method of Child class.

Upvotes: 2

Related Questions