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.
Related
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.)
I am implementing multiple RL agents which share a lot of common attributes and methods but differ in only one. Namely the one that calculates the td_error. Out of the top of my head I can think of 3 options to implement this:
Use an Agent abstract class (ABCMeta) and let the subclasses each implement all their methods.
Use a normal base class Agent, implement all the common methods and just do pass on the one that is specific to each subclass.
Use just one class Agent and use an attribute to specify the type of td_error to calculate and then just use if else to achieve the specific behavior.
Here is what I don't like about each option:
It seems I would need to repeat myself when implementing the common methods in each subclass.
It would be possible to create instances of the base class Agent but it wouldn't work since the specific function is not defined.
It is ugly and seems very naive.
I have been presented with this situation before and I normally go with option 2. but I am pretty sure there is a more correct way of achieving this.
You most definitely do not have to repeat yourself with Abstract class. If you define methods without decorating them as abstract, they will work just fine and can be used in child classes.
from abc import ABC, abstractmethod
class Polygon(ABC):
def amPolygon(self):
print("I am polygon")
#abstractmethod
def noofsides(self):
raise NotImplementedError
class Triangle(Polygon):
# overriding abstract method
def noofsides(self):
print("I have 3 sides")
class Pentagon(Polygon):
# overriding abstract method
def noofsides(self):
print("I have 5 sides")
R = Pentagon()
R.amPolygon()
I have a pretty big class that i want to break down in smaller classes that each handle a single part of the whole. So each child takes care of only one aspect of the whole.
Each of these child classes still need to communicate with one another.
For example Data Access creates a dictionary that Plotting Controller needs to have access to.
And then plotting Controller needs to update stuff on Main GUI Controller. But these children have various more inter-communication functions.
How do I achieve this?
I've read Metaclasses, Cooperative Multiple Inheritence and Wonders of Cooperative Multiple Inheritence, but i cannot figure out how to do this.
The closest I've come is the following code:
class A:
def __init__(self):
self.myself = 'ClassA'
def method_ONE_from_class_A(self, caller):
print(f"I am method ONE from {self.myself} called by {caller}")
self.method_ONE_from_class_B(self.myself)
def method_TWO_from_class_A(self, caller):
print(f"I am method TWO from {self.myself} called by {caller}")
self.method_TWO_from_class_B(self.myself)
class B:
def __init__(self):
self.me = 'ClassB'
def method_ONE_from_class_B(self, caller):
print(f"I am method ONE from {self.me} called by {caller}")
self.method_TWO_from_class_A(self.me)
def method_TWO_from_class_B(self, caller):
print(f"I am method TWO from {self.me} called by {caller}")
class C(A, B):
def __init__(self):
A.__init__(self)
B.__init__(self)
def children_start_talking(self):
self.method_ONE_from_class_A('Big Poppa')
poppa = C()
poppa.children_start_talking()
which results correctly in:
I am method ONE from ClassA called by Big Poppa
I am method ONE from ClassB called by ClassA
I am method TWO from ClassA called by ClassB
I am method TWO from ClassB called by ClassA
But... even though Class B and Class A correctly call the other children's functions, they don't actually find their declaration. Nor do i "see" them when i'm typing the code, which is both frustrating and worrisome that i might be doing something wrong.
Is there a good way to achieve this? Or is it an actually bad idea?
EDIT: Python 3.7 if it makes any difference.
Inheritance
When breaking a class hierarchy like this, the individual "partial" classes, we call "mixins", will "see" only what is declared directly on them, and on their base-classes. In your example, when writing class A, it does not know anything about class B - you as the author, can know that methods from class B will be present, because methods from class A will only be called from class C, that inherits both.
Your programming tools, the IDE including, can't know that. (That you should know better than your programming aid, is a side track). It would work, if run, but this is a poor design.
If all methods are to be present directly on a single instance of your final class, all of them have to be "present" in a super-class for them all - you can even write independent subclasses in different files, and then a single subclass that will inherit all of them:
from abc import abstractmethod, ABC
class Base(ABC):
#abstractmethod
def method_A_1(self):
pass
#abstractmethod
def method_A_2(self):
pass
#abstractmethod
def method_B_1(self):
pass
class A(Base):
def __init__(self, *args, **kwargs):
# pop consumed named parameters from "kwargs"
...
super().__init__(*args, **kwargs)
# This call ensures all __init__ in bases are called
# because Python linearize the base classes on multiple inheritance
def method_A_1(self):
...
def method_A_2(self):
...
class B(Base):
def __init__(self, *args, **kwargs):
# pop consumed named parameters from "kwargs"
...
super().__init__(*args, **kwargs)
# This call ensures all __init__ in bases are called
# because Python linearize the base classes on multiple inheritance
def method_B_1(self):
...
...
class C(A, B):
pass
(The "ABC" and "abstractmethod" are a bit of sugar - they will work, but this design would work without any of that - thought their presence help whoever is looking at your code to figure out what is going on, and will raise an earlier runtime error if you per mistake create an instance of one of the incomplete base classes)
Composite
This works, but if your methods are actually for wildly different domains, instead
of multiple inheritance, you should try using the "composite design pattern".
No need for multiple inheritance if it does not arise naturally.
In this case, you instantiate objects of the classes that drive the different domains on the __init__ of the shell class, and pass its own instance to those child, which will keep a reference to it (in a self.parent attribute, for example). Chances are your IDE still won't know what you are talking about, but you will have a saner design.
class Parent:
def __init__(self):
self.a_domain = A(self)
self.b_domain = B(self)
class A:
def __init__(self, parent):
self.parent = parent
# no need to call any "super...init", this is called
# as part of the initialization of the parent class
def method_A_1(self):
...
def method_A_2(self):
...
class B:
def __init__(self, parent):
self.parent = parent
def method_B_1(self):
# need result from 'A' domain:
a_value = self.parent.a_domain.method_A_1()
...
This example uses the basic of the language features, but if you decide
to go for it in a complex application, you can sophisticate it - there are
interface patterns, that could allow you to swap the classes used
for different domains, in specialized subclasses, and so on. But typically
the pattern above is what you would need.
What is the reason to create components and delegate behavior through them when we can add dependency directly to the method? To me, the latter seem to keep the door open for a behavior to change for existing objects, thus create looser couplings?
Composition/delegation:
class Human:
def __init__(self, legs):
self._legs = legs
def run(self):
self._legs.run()
def walk(self):
self._legs.run()
Inject dependency straight to method:
class Human:
def run(self, legs):
legs.run()
def walk(self, legs):
legs.walk()
Tell me, why should I bother with composition at all?
You should only use composition if it serves a purpose. In your example it serves no purpose since you could just call the methods directly on legs and don't bother with Human at all.
Expanding on your example, composition would make sense if each Human instance had its own distinct legs instance. In that case you need to keep track of which legs belongs to which Human, and the first example solves that.
I really don't know how to word this problem, so I'll try to explain it with an example.
Let's say I have three GUI classes:
Base Surface class
Detailed Surface Class
Sprite Class
All of them are independent of each other, no inheritance among them.
Now I have a function "drag()" that makes a surface/sprite dragable, and I want to implement this function as a method for all three of them.
Since it's the exact same code for all implementations I find it annoying, cumbersome and bad practice to rewrite the code.
The only thing I came up with so far was to make a saperate class for it and inherit this class. But that also doesn't seem to be the way to go.
I'd be very thankfull for some advice.
EDIT
Another example with a slightly different setup - I have the following classes:
BaseSurface
Dragable
Resizable
EventHandler
Only the first one is independent, the others depend on the first (must be inherited).
The end user should, without any effort, be able to choose between a simple BaseSurface, one with that implements dragable, one with resizable, one with eventHandler, and any combination. By "without any effort" I mean the end user should not have to make e custom Class and inherit the desired classes plus call the appropriate methods (init, update, ...) that some classes share.
So what I could do is make a class for every possible combination, eg.
"BaseSurfaceDrag", "BaseSurfaceDragResize", ...
which will get messy really quickly. Whats a different and better approach to this?
This is exactly the kind of case that you should use a parent class for. In both cases it looks like your parent class (logically) should be something like:
class Drawable(object):
def drag(self, *args, **kwargs):
"""Drag and drop behavior"""
# Your code goes here
Then each of your other classes inherits from that
class BaseSurface(Drawable):
# stuff
class DetailedSurface(Drawable):
# stuff
class Sprite(Drawable):
# stuff
In the second case what you have are interfaces, so you could logically do something like:
class DragInterface(object):
"""Implements a `drag` method"""
def drag(self):
"""Drag and drop behavior"""
# Your code goes here
class ResizeInterface(object):
"""Implements a `resize` method"""
def resize(self):
"""Drag and drop resize"""
# Code
class EventHandlerInterface(object):
"""Handles events"""
def handle(self, evt):
# Code
class MyNewSurface(BaseSurface, DragInterface, ResizeInterface):
"""Draggable, resizeable surface"""
# Implement here