I'm apologizing in advance if this question was already answered, I just couldn't find it.
When using multiple inheritance, how can I use a method of a specific parent?
Let's say I have something like this
Class Ancestor:
def gene:
Class Dad(Ancestor):
def gene:
...
Class Mom(Ancestor):
def gene:
...
Class Child(Dad,Mom):
def gene:
if(dad is dominant):
#call dad's gene
else:
#call mom's gene
How can I do that? The super() doesn't have the option the specify the specific parent.
Thanks!
Edit: Forgot to mention an extremely important detail - the methods are of the same name and are overridden. Sorry, and thanks again!
That's not what super is for. super is just meant to call the next item in the inheritance hierarchy, whatever it is - in other words, it's supposed to be used when you don't know or care what that hierarchy is.
For your case, you probably just want to call the method directly. But note that you don't actually need to deal with ancestors at all, because methodA and methodB are not overridden anyway: so you can just call them on self:
if whatever:
self.methodA()
else:
self.methodB()
If you are in the situation where you have overridden methods, you will need to specify the ancestors:
class C(A, B):
def methodA(self):
if whatever:
A.methodA(self)
else:
B.methodA(self)
Related
In a python program, I implemented some class A, and a subclass B which extends some of A's methods and implements new ones. So it's something that looks like this.
class A:
def method(self):
print("This is A's method.")
class B(A):
def method(self):
super().method()
print("This is B's method.")
def another_method(self):
pass
Later, I wanted to use an object which would have access to all of B's methods, except for a small change in method: this object would have to first call A.method, and then do other things, different from what I added in B.method. I thought it was natural to introduce a class C which would inherit from B but modify method, so I defined C like this.
class C(B):
def method(self):
super(B, self).method()
print("This is C's method.")
Everything seems to work as I expect. However, I stumbled across this question and this one, which both address similar problems as what I described here. In both posts, someone quickly added a comment to say that calling a grandparent method in a child when the parent has overridden this method is a sign that there is something wrong with the inheritance design.
How should I have coded this? What would be a better design? Of course this is a toy example and I guess the answer might depend on the actual classes I defined. To give a more complete picture, let's say the method method from the example represents a single method in my actual program, but the method another_method represents many different methods.
hope that you're all fine. I need to do some home-work, I came up with a doubt that I don't know if it can be resolved in this way. Do you mind if you can help me? Thanks anyway.
Suppose we have this:
class human:
def dress(self, weather):
return color(weather)
class girl(human):
def color(self, weather):
if weather == 'rainy':
print('red')
else:
print('blue')
Can I do this? Because at first sight I have a problem that color(), at Human, is undefined (logically). You may ask, why are you thinking this way? Because are the instructions to solve the problem. Which is the best solve it?
Thanks again!
Yes, you can do that. It's not uncommon to have methods in a superclasses that are left to be defined by the subclasses. Usually the superclass will have a placeholder implementation that throws an exception indicating that the subclass needs to define it - however that isn't required for this to work.
class human:
def dress(self, weather):
return self.color(weather)
def color(self, weather):
raise NotImplementedError("Subclass needs to define this.")
class girl(human):
def color(self, weather):
if weather == 'rainy':
c = 'red'
else:
c = 'blue'
print(c)
return c
Some base classes aren't meant to be used directly and require the subclass to implement methods that the base class calls. If you subclass such a class and fill in the implementation for the needed methods.. the methods that the base class already has defined which calls them will work.
For instance, say we have a girl instance. And we want it to dress for the weather. Even though the subclass doesn't define dress() it still has that method because it inherited it.
>>> mary = girl()
>>>
>>> mary.dress("rainy")
red
At runtime, the interpreter runs the code for dress() and in it sees color(). It then looks for that function on the girl and finds it. Doesn't matter whether the base class defines it or not.
No you can't call child class method from parent class unless methods have same name.
One it can be done if you create a same method "color" in parent class also.
I have a class inherited from project.task named ProjectTask
The class has a copy method that overrides the copy function from project.task it's named Task
I need to run the base copy function from my class instead of the one of the parents class
this is my class code:
#api.multi
#api.returns('self', lambda value: value.id)
def copy(self, default=None):
if default is None:
default = {}
if not default.get('name'):
default['name'] = self.name.id
return super(ProjectTask, self).copy(default) #<-- I don't want to call the inherited class method I want to call the base class method instead
This is the copy method from the base class (Task)
#api.multi
#api.returns('self', lambda value: value.id)
def copy(self, default=None):
if default is None:
default = {}
if not default.get('name'):
default['name'] = _("%s (copy)") % self.name
return super(Task, self).copy(default) # <-- I want to run this method from my class (ProjectTask) which is the child class
Any advice will be more than welcome
With the parent class implementation you show, calling it with your own default should do what you want, as it will just pass it through to its own parent with no changes. (At least, that's true with the bare method code, I don't know what the odoo decorators do to change things.)
But if you really do need to skip over it for some non-obvious reason, you probably can do it. Generally speaking, these approaches will only work as intended if you don't expect your class to ever be used with multiple inheritance. If your MRO gets complicated, then you really want to be doing the normal thing with super and making all your methods play nicely together.
One option for skipping an inherited method is to directly name the class you want your call to go to (i.e. your grandparent class).
class Base():
def foo(self):
print("Base")
class Parent(Base):
def foo(self):
print("Parent")
super().foo() # super() in Python 3 is equivalent to super(Parent, self)
class Child(Parent):
def foo(self):
print("Child")
Base.foo(self) # call Base.foo directly, we need to pass the self argument ourselves
Another option would be to change the argument you give to super to name the parent class instead of your own class. Usually that's a newbie error, but if that's really what you want, it's allowed (though I'd strongly recommend adding a comment to the code explaining that you really do want that behavior!
class Child(Parent):
def foo(self):
print("Child")
super(Parent, self).foo() # Note: Deliberately skipping over Parent.foo here!
A final note: If you find yourself wanting to skip a parent class's implementation of some of its methods, perhaps you should reconsider if you should really be inheriting from it at all. It may be that you really want to be inheriting from the same base class as it instead, and skipping the middle class altogether. Obviously, this has its own limitations (maybe some library code does type checking for that class), but if you find yourself fighting the inheritance machinery, it may be that you're doing things the hard way, and there's an easier alternative.
I want to be able to recycle a method from a parent class that uses a second method in that parent class. However the second method is overridden in the child class. I want the recycled parent method to use the new overridden second method when it is called from the child class. An example of how I want it to work will hopefully make this clearer:
class Parent:
def method1(self, num):
return num**2
def method2(self, list_size):
return [self.method1(i) for i in range(list_size)] #List of squares
class Child(Parent):
def method1(self, num): #Overrides corresponding parent method
return num**3
def method2(self, list_size):
return super().method2(list_size) #Returns a list of cubes using child's method 1.
Is this possible in python3? Or will calling the parent's method 2 also use the parent's method 1? I'm hoping to reuse large parts of a parent class as the child class differs in only a few ways. The methods nesting like that in the parent class make it a lot more general.
Thanks!
EDIT: I forgot to test it with simple code! It does work like I wanted if anyone was wondering!
Short answer: yes.
Just tried a slightly modified version of your code with prints.
class Parent:
def method1(self):
print("Parent method1")
def method2(self):
print("Parent method2")
self.method1()
class Child(Parent):
def method1(self):
print("Child method1")
def method2(self):
print("Child method2")
super().method2()
c = Child()
c.method2()
This is the output:
Child method2
Parent method2
Child method1
As you can see, the method1 used is the child one.
Yes, this works the way you want it to.
You can easily test this yourself. Unless you pass in nothing but 0s and 1s, it should be pretty obvious whether they're getting squared or cubed.
And, in cases where it's less obvious, just add a debugger breakpoint to Child.method1 and Parent.method1 and see which one gets hit. Or add print(f'Child1.method({self}, {num})') to the method and see if it gets printed out.
If you're coming from another language with C++ OO semantics instead of Smalltalk OO semantics, it may help to think of it this way: Every method is always virtual.
Are __init__ calls virtual? Yes.
What if you call a method during __init__? Yes.
What if you call a method inside a super call? Yes.
What about a #classmethod? Yes.
What if…? Yes.
The only exceptions are when you go out of your way to explicitly tell Python not to make a virtual function call:
Calls on super() use the implementation from the next class in the MRO chain, because that's the whole point of super.
If you grab a parent's bound method and call that, like Parent.method1(self, num), you obviously get Parent.method1, because that's the whole point of bound methods.
If you go digging into the class dicts and run the descriptor protocol manually, you obviously get whatever you do manually.
If you're not trying to understand Python in terms of Java, and just want a deeper understanding of Python on its own terms, what you need to understand is what happens when you call self.method1(i).
First, self.method1 doesn't know or care that you're going to call it. It's an attribute lookup, just like, say, self.name would be.
The way Python resolves this is described in the Descriptor HOWTO, but an oversimplified version looks like this:
Does self.__dict__ have anything named method1? No.
Does type(self).__dict__ have anything named method1? Yes.
Return type(self).__dict__['method1'].__get__(self).
If that second lookup failed, Python would loop over type(self).mro() and do the same test for each one. But here, that doesn't come up. type(self) is always going to be Child for an instance of Child, and Child.__dict__['method1'] exists, so it binds Child.method to self, and the result is what self.method1 means.
In Python, I want to know if it is necessary to include __init__ as the first method while creating a class, as in the example below:
class ExampleClass:
def __init__(self, some_message):
self.message = some_message
print "New Class instance created, with message:"
print self.message
Also, why do we use self to call methods?
Can someone explain the use of "self" in detail?
Also, why do we use pass statement in Python?
No, it isn't necessary.
For example.
class A(object):
def f():
print 'foo'
And you can of course use it, in this manner:
a = A()
a.f()
In fact you can even define a class in this manner.
class A:
pass
However, defining __init__ is a common practice because instances of a class usually store some sort of state information or data and the methods of the class offer a way to manipulate or do something with that state information or data. __init__ allows us to initialize this state information or data while creating an instance of the class.
Here is a complete example.
class BankAccount(object):
def __init__(self, deposit):
self.amount = deposit
def withdraw(self, amount):
self.amount -= amount
def deposit(self, amount):
self.amount += amount
def balance(self):
return self.amount
# Let me create an instance of 'BankAccount' class with the initial
# balance as $2000.
myAccount = BankAccount(2000)
# Let me check if the balance is right.
print myAccount.balance()
# Let me deposit my salary
myAccount.deposit(10000)
# Let me withdraw some money to buy dinner.
myAccount.withdraw(15)
# What's the balance left?
print myAccount.balance()
An instance of the class is always passed as the first argument to a method of the class. For example if there is class A and you have an instance a = A(), whenever you call a.foo(x, y), Python calls foo(a, x, y) of class A automatically. (Note the first argument.) By convention, we name this first argument as self.
In addition to other answers, one point in your question that has not been addressed :
Is it necessary to include __init__ as the first function
everytime in a class in Python?
The answer is no. In the case you need a constructor, it can be located at any position of your code, although the conventional and logical place is the beginning.
You don't need to put it in your Class; it is the object constructor.
You will need it if you want things to happen automatically to your object when it is instantiated.
No, it is not necessary to use the init in a class. It's a object constructor that define default values upon calling the class.
If you're programming in OOP manner and ought to have a basic structure of your class. You often will need this.
I read your other sub-question regarding
Can u explain about the use of "self"??? – harsh Jul 28 '11 at 5:13
Please refer to this post in stackoverflow. There's a lot of useful links to help you better understand python's init function.
Python __init__ and self what do they do?
Is not necessary the "init" statement, besides the "pass" statement is just used for skip, either to the next part of the code, or just skip cause was reached a special part like an "if" statement.
I initially struggled with that question too then I realize it is just another way to store certain data to your object and that data can be passed to any object method you define since your instance method has a self argument that can point back to the data you created in the init method.
No, it is not necessary but it helps in so many ways. people from Java or OOPS background understand better.
For every class instance, there is an object chaining that needs to complete when we instantiate any class by creating an object.
If we don’t put it compiler/interpreter puts it. But when we need some action to be formed while creating an object then we must have to pass it.
first.py
-------
class A:
def one(self):
print("something")
second.py
----------
from first import A
class B:
def test(self):
a = A()
x = a.one()
print(x)
test(any)
**output:**
something
None
Sure that this not required.
Please read more about defining python classes in this tutorial here.
Read more about __init__ in the documentation here and at What do __init__ and self do in Python?.
In general __init__ is a kind of constructor that is called automatically and allows you to perform any additional actions(adding variables, calling any methods and so on - the idea is to have the ability to initialize instance since it is already created and now you may need to do something with it before proceeding - for example remember creation time or serializing its initial state and so on) while creating object. So if you don't need to do some special preparation you may skip using it.
Its not necessary...
It's just function that runs everytime an object is created from your class...
And it can be helpful if you want every object have some things in common