A.Raouf
A.Raouf

Reputation: 2320

How to force python to point to child even parent call?

Now I have

class A:
    def start(self):
       return True

class B(A):
    def start(self):
       return False

Now if I want to make all the A() calls point or redirect to B class for example

s=A()
s.start()

It should return False as A is overridden with B to return False

Is that possible?

Okay Edit My case is in Django view which is called in 3rd party package URLs and I want to override and the package call my child which I override it, But I solved it by overriding the url itself, so I'm asking if it can be done as a pythonic way not in a django way.

Upvotes: 0

Views: 52

Answers (1)

Mad Physicist
Mad Physicist

Reputation: 114320

Technically, @BryanOakley's [now deleted] answer is the right one: if you want to use the features of the child class, instantiate the child class.

That being said, you can still access the parent's methods from the child. Let's say you have

class A:
    def start(self): return True
    def finish(self): return True


class B:
    def start(self): return False
    def finish(self): return False

If your reason for wanting to instantiate A, but use the start method of B is that you want the finish method of A, it is always much safer to call the methods of the parent on the child than vice versa:

b = B()
b.start()
A.finish(b)

This is a perfectly reasonable technique, and is used quite commonly. There is nothing inherently unsafe about it if you use it with moderate care.

Now, as it happens, Python uses duck typing. When you access a particular method or attribute, it will attempt to access that method or attribute directly, usually without checking the type of the object. This means that technically, and I really do not recommend this, you can do

a = A()
B.start(a)
a.finish()

If the start method of B does not access something that exists in the child but not in the parent, you can get away with this. But please don't, code has a tendency to change and something you "can get away with" now will usually come to bite you later.

EDIT

It sounds, after your edit, that you are asking about monkey patching perhaps. It appears that you actually want to replace the method start in an existing class with an alternative implementation that you defined elsewhere. This is not generally a good idea: it is much better to configure things properly up front whenever possible. That being said you can do something like this:

# Defined externally
class A:
    def start(self): return True

# Defined by you
def start(self): return False

A.start = start

a = A()
a.start()  # False

If you have only a single method in mind, you can replace it directly, as shown here. You do not need a whole class definition for that. You can monkey patch a class (or other attribute) at the module level using a very similar technique. The change will be visible throughout your code since all imported modules normally point to the same object. Monkey patching a method on an instance is also possible, but less trivial.

Upvotes: 2

Related Questions