Conditional Inheritance based on arguments in Python

2024/9/8 8:24:21

Being new to OOP, I wanted to know if there is any way of inheriting one of multiple classes based on how the child class is called in Python. The reason I am trying to do this is because I have multiple methods with the same name but in three parent classes which have different functionality. The corresponding class will have to be inherited based on certain conditions at the time of object creation.

For example, I tried to make Class C inherit A or B based on whether any arguments were passed at the time of instantiating, but in vain. Can anyone suggest a better way to do this?

class A:def __init__(self,a):self.num = adef print_output(self):print('Class A is the parent class, the number is 7',self.num)class B:def __init__(self):self.digits=[]def print_output(self):print('Class B is the parent class, no number given')class C(A if kwargs else B):def __init__(self,**kwargs):if kwargs:super().__init__(kwargs['a'])else:super().__init__()temp1 = C(a=7)
temp2 = C()temp1.print_output()
temp2.print_output()

The required output would be 'Class A is the parent class, the number is 7' followed by 'Class B is the parent class, no number given'.

Thanks!

Answer

Whether you're just starting out with OOP or have been doing it for a while, I would suggest you get a good book on design patterns. A classic is Design Patterns by Gamma. Helm. Johnson and Vlissides.

Instead of using inheritance, you can use composition with delegation. For example:

class A:def do_something(self):# some implementationclass B:def do_something(self):# some implementationclass C:def __init__(self, use_A):# assign an instance of A or B depending on whether argument use_A is Trueself.instance = A() if use_A else B()def do_something(self):# delegate to A or B instance:self.instance.do_something()

Update

In response to a comment made by Lev Barenboim, the following demonstrates how you can make composition with delegation appear to be more like regular inheritance so that if class C has has assigned an instance of class A, for example, to self.instance, then attributes of A such as x can be accessed internally as self.x as well as self.instance.x (assuming class C does not define attribute x itself) and likewise if you create an instance of C named c, you can refer to that attribute as c.x as if class C had inherited from class A.

The basis for doing this lies with builtin methods __getattr__ and __getattribute__. __getattr__ can be defined on a class and will be called whenever an attribute is referenced but not defined. __getattribute__ can be called on an object to retrieve an attribute by name.

Note that in the following example, class C no longer even has to define method do_something if all it does is delegate to self.instance:

class A:def __init__(self, x):self.x = xdef do_something(self):print('I am A')class B:def __init__(self, x):self.x = xdef do_something(self):print('I am B')class C:def __init__(self, use_A, x):# assign an instance of A or B depending on whether argument use_A is Trueself.instance = A(x) if use_A else B(x)# called when an attribute is not found:def __getattr__(self, name):# assume it is implemented by self.instancereturn self.instance.__getattribute__(name)# something unique to class C:def foo(self):print ('foo called: x =', self.x)c = C(True, 7)
print(c.x)
c.foo()
c.do_something()
# This will throw an Exception:
print(c.y)

Prints:

7
foo called: x = 7
I am A
Traceback (most recent call last):File "C:\Ron\test\test.py", line 34, in <module>print(c.y)File "C:\Ron\test\test.py", line 23, in __getattr__return self.instance.__getattribute__(name)
AttributeError: 'A' object has no attribute 'y'
https://en.xdnf.cn/q/73067.html

Related Q&A

Slice endpoints invisibly truncated

>>> class Potato(object): ... def __getslice__(self, start, stop): ... print start, stop ... >>> sys.maxint 9223372036854775807 >>> x = sys.maxint + 69 >…

Selenium Webdriver with Java vs. Python

Im wondering what the pros and cons are of using Selenium Webdriver with the python bindings versus Java. So far, it seems like going the java route has much better documentation. Other than that, it s…

asyncio - how many coroutines?

I have been struggling for a few days now with a python application where I am expecting to look for a file or files in a folder and iterate through the each file and each record in it and create objec…

Calculating a 3D gradient with unevenly spaced points

I currently have a volume spanned by a few million every unevenly spaced particles and each particle has an attribute (potential, for those who are curious) that I want to calculate the local force (ac…

deleting every nth element from a list in python 2.7

I have been given a task to create a code for. The task is as follows:You are the captain of a sailing vessel and you and your crew havebeen captured by pirates. The pirate captain has all of you stand…

Bradley-Roth Adaptive Thresholding Algorithm - How do I get better performance?

I have the following code for image thresholding, using the Bradley-Roth image thresholding method. from PIL import Image import copy import time def bradley_threshold(image, threshold=75, windowsize=5…

How to display all images in a directory with flask [duplicate]

This question already has answers here:Reference template variable within Jinja expression(1 answer)Link to Flask static files with url_for(2 answers)Closed 6 years ago.I am trying to display all image…

Reindex sublevel of pandas dataframe multiindex

I have a time series dataframe and I would like to reindex it by Trials and Measurements.Simplified, I have this:value Trial 1 0 131 32 42 3 NaN4 123…

How to publish to an Azure Devops PyPI feed with Poetry?

I am trying to set up Azure Devops to publish to a PyPI feed with Poetry. I know about Twine authentication and storing credentials to an Azure Key Vault. But is there any more straightforward method?…

Python Regex Match Before Character AND Ignore White Space

Im trying to write a regex to match part of a string that comes before / but also ignores any leading or trailing white space within the match.So far Ive got ^[^\/]* which matches everything before the…