When to call super(..) and when not to? - python

I have a simple question regarding the programming style/convention in python when it comes to superclasses, and calling their methods.
Lets assume I have
class A():
def a(self):
print "a"
and I have another class, class B. Is it better to do :-
class B(A):
pass
vs
class B(A):
def a(self):
super(B,self).a()
I eventually want to do : b = B(); b.a()
Is there any difference in the two, except for readability?

You use super when an overriding method should do something in addition to what its base class's method is doing.
For example, if you have class Point and class Circle(Point) and want to implement def move, circles can just reuse point's method they inherit - since moving a circle is precisely moving the circle's centre point.
But if you have class Monster and class Dragon(Monster)... you might want to scorch the land when a dragon walks past, that other monsters would not do. So you'd say that dragon movement is same as normal movement, with some fire added:
class Dragon(Monster):
def move(self, destination):
super(Monster, self).move(destination)
destination.add_some_fire()

If you aren't changing or extending the functionality of the parent method, then there's no reason to even define it - let alone override it. If you don't define it, then the parent method will be used.

Related

Can I implement an abstact method by a concrete method with a different name?

i am experimenting with implementation of the monte-carlo-tree-search algorithm for the travelling salesman problem. In this context, I have created a class that without going into details looks somewhat like these:
class Position:
def __init__(self, salesman, cities):
self.salesman= salesman
self.cities= cities
def unvisited_cities(self):
result = {}
for name, city in self.cities.items():
if city.not_visited():
result[name] = city
return result
def travel_to_city(self, city_name):
new_salesman = self.salesman.travel_to(city_name)
return Position(new_salesman, self.cities)
Now, I want to declare this class as a child class for an abstact class:
class AbstractGamePosition(metaclass=abc.ABCMeta):
#abc.abstractmethod
def possible_actions(self):
return
But here, I face a problem. Abstact class demands possible_actions method. In my concrete Position class, method that returns a set of all possible actions from is called unvisited_cities, because for the salesman problem only those cities can be the next targets that have not been visited yet. Is it possible to declare a Position as a child class of an AbstactGamePosition abstact class, and somehow let Python know that abstact method possible_actions is implemented in Position class by a concrete method unvisited_cities?
In naive language it could be something like this:
Position <- AbstactGamePosition:
AbstactGamePosition.possible_actions = Position.unvisited_cities
However, Python does not have such a construction. Can this be somehow solved?
Obviously, this can be solved through an interface class:
class Interface(AbstactGamePosition):
def __init__(self, position, concrete_method):
self.position = position
self._possible_actions = concrete_method
def possible_actions(self):
return self._possible_actions(self.position)
position = Position(salesman, cities)
interface = Interface(position, Position.unvisited_cities)
But this looks so sloppy that I find this disgusting.
Given the information in the comments (that you don't want to have a hard dependency between Position and AbstractGamePosition), I think you're looking for the adapter pattern. Your Interface class is pretty close, though I agree that that level of reflection is unwarranted in this situation.
I would recommend created a small class alongside Position that is specifically for position, and that class can delegate to the original.
# (Type annotations provided for clarity; they are optional)
class PositionAdapter(AbstractGamePosition):
def __init__(self, position: Position):
self.position = position
def possible_actions(self):
return self.position.unvisited_cities()
Then, when you want to use a Position in a situation where an AbstractGamePosition is expected, you simply write
my_abstract_game_position = PositionAdapter(my_original_position)
and you can call possible_actions on my_abstract_game_position.
You will have to write one of these adapter classes for each class you want adapted to this abstract parent without a hard dependency. But it's not a lot of boilerplate (five lines of code, basically), so it's worth it if your goal is to keep all of these classes as loosely coupled as possible.
Just implement the method by its expected and required name. You can call you actual implementation internally:
class Position(AbstractGamePosition):
...
def unvisited_cities(self):
...
def possible_actions(self):
return self.unvisited_cities()
In fact, you can simply assign the unvisited_cities method to the required name, which has the same outcome:
class Position(AbstractGamePosition):
...
def unvisited_cities(self):
...
possible_actions = unvisited_cities
ABCMeta literally only cares about the name being defined with an object that does not have an __isabtractmethod__ attribute set to True: that's it.
You can patch Position with
Position.possible_actions = Position.unvisited_cites
then register Position as a subclass of the abstract base class.
AbstractGamePosition.register(Position)
(If fact, registering a virtual subclass doesn't even require the name to be properly defined; you can do so without defining Position.possible_actions.)
(Assuming you can't change the definition of Position to inherit from the abstract class. If you can, #deceze's answer has you covered.)

disable inheritance of some methods

suppose I have a class which has 10 methods,
(i write pass here, but assume they would have some implementation)
class KlassOne:
def method_one(self, x):
pass
def method_two(self, y, z):
pass
...
def method_five(self, a):
pass
...
def method_ten(self, b):
pass
and a second class which inherits from the first one.
class KlassTwo(KlassOne):
def method_eleven(self, w):
pass
but KlassTwo does not want all ten methods of KlassOne,
let us say KlassTwo wants to inherit only these four methods,
wanted_methods = [method_one, method_three, method_eight, method_nine]
and the rest are not applicable for KlassTwo
one example could be,
KlassOne is Person
and KlassTwo is Robot
and method_five is EatsFood
so, our Robot does not want to inherit EatsFood
whereas method_one is BodyWeight, and let us assume it makes sense for both Person and Robot, so Robot wants to inherit method_one.
but how could this partial inheritance be achieved???
one way to do this is by using NotImplemented, for example,
class KlassTwo(KlassOne):
def method_five(self, a):
raise NotImplemented
and do the same for each method that is not wanted.
or the other way could be to use Composition, like,
class KlassTwo:
def __init__(self, x):
self.t = KlassOne.method_one(self, x)
something like that, and only use the methods that are wanted.
but I would like to use inheritance, and completely disable the inheritance of some methods,
that is something like,
class KlassOne:
#not_inheritable
def method_five(self, a):
pass
so that no subclass would get method_five.
how do I achieve this?
or give a list in KlassTwo, again like,
wanted_methods = [method_one, method_three, method_eight, method_nine]
and ensure that only these get inherited.
This doesn't directly answer your question of "How to inherit partially", rather is suggesting alternative in case of we're facing a XYZ problem.
Considering your human and robot example, it seems like your base class is not quite a baseline class(or generic) for what you're trying to do.
It might be better to define base class as Union of subclasses you're going to have, and add other Might-need-might-not features like EatsFood in subclass, or as Mixin.
For example, let's say we want to have Human, Humanoids, Monkey and Marcus Wright.
What they have in common: They are human-like entities with human shape.
Let's define base class with what usual human-like entities could do.
from __future__ import annotations
class HumanLike:
"""
Base class for human-like entities
"""
def __init__(self):
# some required attributes or setups
pass
def left_punch(self, target: HumanLike):
"""punch target with left fist"""
def right_hook(self, target: HumanLike):
"""Give nice right hook to target"""
def walk(self, pos):
"""Walk towards pos"""
Now we want to make Human, Humanoids and monkey. Then we can find something common between Human and Monkey, make such as mixin.
class BiologicalMixin:
"""
Mixin class for biological entities with basic needs
"""
def eat(self, food):
"""Eats given food"""
def breath(self):
"""Give that lung a fresh 'n nice air"""
class RoboticMixin:
"""
Mixin for Non-Biological entities with robot needs
"""
def recharge(self):
"""recharge energy"""
def robot_dance(self):
"""Pull out some sick moves that weak creatures can't"""
And then all we have to do would be subclassing these to make various stuffs.
class Human(HumanLike, BiologicalMixin):
"""
An obviously human like being with biological needs
"""
class Humanoid(HumanLike, RoboticMixin):
"""
A Human shaped robot
"""
class Monkey(HumanLike, BiologicalMixin):
"""
They love bananas!
"""
class TerminatorHybrid(HumanLike, BiologicalMixin, RoboticMixin):
"""
Marcus Wright would be here
"""
This is more common way of inheritance - Inheriting optionally isn't an inheritance.
If you really need such, best bet I can think of is to use composition and map methods you want manually.

Override a method of an attribute

I have a class that has an attribute as an object from another class. A third class inherits from the first class, and in there, I want to override the attribute's method ...
class Car:
def __init__(self, door):
self.door = door
class Door:
def __init__(self, color):
self.color = color
def change_color(self):
pass
class CarConstruct(Car):
def __init__(self):
super(CarConstruct, self).__init__(Door('red'))
# Here, I want to override self.door.change_color method
What is the best way to override in such a situation?
This technique is called "monkey patching". In general it should be avoided, because it makes the code very hard to understand and reason about. Avoid it unless you have a very good cause. One of the good causes might be to mock a method in unit tests.
If you still want to monkey patch just one method on one object self.door - check out this answer.

Class Method; returning given input

I have the code:
class Triangle(Coordinate):
def __init__(self,xcoord,ycoord,color):
self.color = color
super().__init__(xcoord,ycoord)
(inheriting from class Coordinate)
And whenever I call it, for example
t1 = Triangle(Coordinate(1,1), Coordinate(2,1), Red)
It only returns the coordinates, how do it make it return the color as well?
The answer has been posted in the comments but I think you misunderstood him, so I am going to elaborate a bit more.
Your class Triangle inherits functions from a parents class of some sort. Even though you didn't write a def __str__(self): in Triangle, it can still be used because it is defined in your parent class, and Triangle inherits functions from the parent class
If you don't want to use any of the parent class' functions, you can redefine it in Triangle. When you call that function on a Triangle Python will prefer to use the def __str__(self): in Triangle before referencing the parent class.
In short, you need to write a new def __str__(self): similar to the one in your parent class, but add another portion in the output that accounts for the color. I hope this helps Charmaine. Good luck!

How do i create a derived class with certain constructors? (python)

This is my class:
class Player(object):
def __init__(self, playernum):
self.playernum = playernum
def play_turn(self, board):
"""This method is passed an instance of ConnectFour.
It should examine the board (using methods on the ConnectFour class...
assume you have it) and eventually call board.play_turn and return"""
pass
So far I understand that if I do:
class Human(Player):
It will make Human() a derived class of Player.
What I would like to do is have a constructor playernum inside this class. Then take the overridden play_turn and print a player number(ie. playernum)...I just want to know how this would be implemented... do I repeat
def play_turn(self,board):
inside the Human class or do I simply put
class Human(Player):
play_turn
and inside the
play_turn(self,board):
"put"
print playernum
I'm kind of new to derivations of classes and the logic behind it. Any input will be highly appreciated. Thanks.
You're correct that to override a method from a parent class, you 'repeat' the method inside the derived class. Your code should end up looking something like:
class Human(Player):
def play_turn(self, board):
print self.playernum
If play_turn is meant to contain shared logic for its derived classes, you want to call the parents' method first:
class Human(Player):
def play_turn(self, board):
super(Human, self).play_turn(board)
print self.playernum

Categories