Inheritance reassurance python - python

So I have looked at multiple examples of inheritance and constructors on here and I am a little unsure of myself.
So as I understand it you can call a class constructor within a constructor.
class A(Z):
def __init__(self):
super().__init__(self)
Right so... would this be a legitimate class call or should I refactor this?
class SubsManagement(Subs, Database_Tables):
def __init__(self, db_file):
Database_Tables.__init__(db_file)
self.conn, self.cur = Database_Tables.connect_database()
Subs.__init__(self.cur)
What would be my other options for this? This is a personal project btw.
EDIT:
Alright, I looked at using a wrapper as per suggestion, but would that be basically making a chain of ancestor classes? If was a little vague as to my personal situation as the example in the non-cooperative classes does not build a constructor with arguments.

Related

TypeError: Can't instantiate abstract class with abstract methods

I've seen similar questions posted here and here, but they don't really answer the problem that I'm having, maybe someone can explain this error to me.
I'm using this backtesting package to create a stock backtesting environment, but I'm making some modifications in my implementation of it. I've created a minimal reproducible example of my main code below:
# pip install backtesting
from backtesting import Strategy
class StrategyParentClass:
def __init__(self, whatever=True):
self.whatever=whatever
class StrategyChildClass(StrategyParentClass, Strategy):
def __init__(self):
super().__init__()
self.title="StrategyTitle"
def next(self):
print("YAY")
child_class_object = StrategyChildClass()
The code right now gives the error:
Traceback (most recent call last):
File "test2.py", line 16, in <module>
child_class_object = StrategyChildClass()
TypeError: Can't instantiate abstract class StrategyChildClass with abstract methods init, next
To explain, I have a parent strategy class, and a child strategy class. The child strategy class inherits the attributes from the parent class, as well as the Strategy class from the backtesting package. When you look at the example code they provide, your strategy class should look like this. So your child class should have a next method in it, which mine does.
However, I'm trying to make my child class inherit from 2 parent classes, which I think is what's giving me the grief. When you delete the , Strategy in the StrategyChildClass(StrategyParentClass, Strategy): line, it'll run without giving an error.
So in this case, how can I instantiate a parent class of my own, and have the child class inherit from IT, AND the imported Strategy class parent, without giving this error? The backtesting package uses this child class' attributes and next method when running the trades.
I cannot speak to your implementation here, but generally speaking, you must implement abstract methods of any base class in a subclass that calls it. (the two abstract methods in 'Strategy' are 'init' and 'next' and you only had the 'next' method in your subclass. This code should solve it, though may not behave how you intend)
# pip install backtesting
from backtesting import Strategy
class StrategyParentClass:
def __init__(self, whatever=True):
self.whatever=whatever
class StrategyChildClass(StrategyParentClass, Strategy):
def __init__(self):
super().__init__()
self.title="StrategyTitle"
def next(self):
print("YAY")
def init(self):
pass
child_class_object = StrategyChildClass()
A good resource that covers this: https://python-course.eu/oop/the-abc-of-abstract-base-classes.php#:~:text=An%20abstract%20method%20is%20a,implementations%20for%20the%20abstract%20methods.
Your problem is that the Strategy class in that library defines an abstract method called init (not __init__) which you must implement. This is obviously terrible naming on their part because it makes it easy to confuse the init method with the constructor of the class.

How to do multiple inheritance from different classes in python using super()?

Lets say we have different kind of people, pianist,programmer and multitalented person.
so, How do i inherit like this? currently this code gives error Multitalented has no attribute canplaypiano.
class Pianist:
def __init__(self):
self.canplaypiano=True
class Programer:
def __init__(self):
self.canprogram=True
class Multitalented(Pianist,Programer):
def __init__(self):
self.canswim=True
super(Pianist,self).__init__()
super(Programer,self).__init__()
Raju=Multitalented()
print(Raju.canswim)
print(Raju.canprogram)
print(Raju.canplaypiano)
Also Please mention some well written article about python inheritance/super() i couldnt find a perfect article with clear explaination. thankyou.
All classes involved in cooperative multiple inheritance need to use super, even if the static base class is just object.
class Pianist:
def __init__(self):
super().__init__()
self.canplaypiano=True
class Programer:
def __init__(self):
super().__init__()
self.canprogram=True
class Multitalented(Pianist,Programer):
def __init__(self):
super().__init__()
self.canswim=True
Raju=Multitalented()
print(Raju.canswim)
print(Raju.canprogram)
print(Raju.canplaypiano)
The order in which the initializers run is determined by the method resolution order for Multitalented, which you can affect by changing the order in which Multitalented lists its base classes.
The first, if not best, article to read is Raymond Hettinger's Python's super() Considered Super!, which also includes advice on how to adapt classes the don't themselves use super for use in a cooperative multiple-inheritance hierarchy, as well as advice on how to override a function that uses super (in short, you can't change the signature).
Dont call super with explicit parent classes. In modern python versions (don't know exactly since which version) you call super without parameters. That is, in you case you should have had only one line, not two:
super().__init__()
In somewhat older versions you need to provide the class explicitly, however you should provide the class of "current" object, and the super function takes care of finding out the parent classes. In you case it should be:
super(Multitalented, self).__init__()

Creating a class as a pool of another class in Python

So I have a question regarding python conventions in python classes. I want to write the most conventional way, but I am not sure if my "technique" is optimal.
In general, I have multiple instances of one class, e.g. Car(), with a method, say drive().
class Car(object):
def drive(self):
pass
And then I want to call car.drive() of all instances of the class Car(). The way I do this usually is:
class Cars():
def __init__(self, num_cars):
self.cars = [Car() for _ in range(num_cars)]
def drive(self):
for car in self.cars:
car.drive()
Of course, usually Car() would have multiple methods and I would want to call all methods of all instances of Car() using the class Cars() and a method there which would call all the methods of the instances.
What do you guys think of this way of doing it? In what way could this be done better and, I guess, more Pythonic?
"Simple is better than complex."
Just use a list and call it cars?

Python inheritance structure

Python 3.6
I just found myself programming this type of inheritance structure (below). Where a sub class is calling methods and attributes of an object a parent has.
In my use case I'm placing code in class A that would otherwise be ugly in class B.
Almost like a reverse inheritance call or something, which doesn't seem like a good idea... (Pycharm doesn't seem to like it)
Can someone please explain what is best practice in this scenario?
Thanks!
class A(object):
def call_class_c_method(self):
self.class_c.do_something(self)
class B(A):
def __init__(self, class_c):
self.class_c = class_c
self.begin_task()
def begin_task(self):
self.call_class_c_method()
class C(object):
def do_something(self):
print("I'm doing something super() useful")
a = A
c = C
b = B(c)
outputs:
I'm doing something super() useful
There is nothing wrong with implementing a small feature in class A and use it as a base class for B. This pattern is known as mixin in Python. It makes a lot of sense if you want to re-use A or want to compose B from many such optional features.
But make sure your mixin is complete in itself!
The original implementation of class A depends on the derived class to set a member variable. This is a particularly ugly approach. Better define class_c as a member of A where it is used:
class A(object):
def __init__(self, class_c):
self.class_c = class_c
def call_class_c_method(self):
self.class_c.do_something()
class B(A):
def __init__(self, class_c):
super().__init__(class_c)
self.begin_task()
def begin_task(self):
self.call_class_c_method()
class C(object):
def do_something(self):
print("I'm doing something super() useful")
c = C()
b = B(c)
I find that reducing things to abstract letters in cases like this makes it harder for me to reason about whether the interaction makes sense.
In effect, you're asking whether it is reasonable for a class(A) to depend on a member that conforms to a given interface (C). The answer is that there are cases where it clearly does.
As an example, consider the model-view-controller pattern in web application design.
You might well have something like
class Controller:
def get(self, request)
return self.view.render(self, request)
or similar. Then elsewhere you'd have some code that found the view and populated self.view in the controller. Typical examples of doing that include some routing lookups or include having a specific view associated with a controller. While not Python, the Rails web framework does a lot of this.
When we have specific examples, it's a lot easier to reason about whether the abstractions make sense.
In the above example, the controller interface depends on having access to some instance of the view interface to do its work. The controller instance encapsulates an instance that implements that view interface.
Here are some things to consider when evaluating such designs:
Can you clearly articulate the boundaries of each interface/class? That is, can you explain what the controller's job is and what the view's job is?
Does your decision to encapsulate an instance agree with those scopes?
Do the interface and class scopes seem reasonable when you think about future extensibility and about minimizing the scope of code changes?

python dynamically changing super

I have a couple of classes and for testing I need to replicate these classes with small modifications. Initially, I was just changing a test class to the class it is supposed to mimic after doing the necessary modifications.
class Class_A(object):
def __init__(self):
do_class_A_stuff
class Class_B(object):
def __init__(self):
do_class_B_stuff
....
class Test(object):
def __init__(self, classToMimic):
doStuffForTest
self.__class__ = classToMimic
which worked fine. However, now I got to the point that I need to run some test method in between do_classX_stuff. So, I can not run the test specific procedure before I change the class, but also after the init of the super. My thought was just to dynamically inherit Test and overwrite some methods to add the testing code where necessary.
class Test(object):
def __init__(self, classToMimic):
self..__bases__ = classToMimic
def methodToOverwrite(self):
doStuffForTest
Is this a good approach and if so, how can I do that or is there a better solution?
Edit: I had this quite wrong, as Marijn pointed out, I am looking for .bases, not super. changed in the above and goggling this, I found a little bit more information.
Why not use a factory to create subclasses:
def test(classToMimic):
class Test(classToMimic):
def methodToOverwrite(self):
doStuffForTest
return Test

Categories