is it possible to create/Initialize class from a superior class' method without inheritance? Currently, I have a method that returns a list of dataframes. Instead of a list I would like to have a new class being initialized that holds the tables' data but also has other methods that can be called from that new class.
A pseudocode example:
superiorObj = SuperiorClass() # initialize superior Class
tbls = superiorObj.extract_tables() #This method should initialize a new Class
clean_tbl = tbls.clean_tbl(tbl_name="Example_TBL") #Normal Dataframe Object
I am a little bit stuck how to accomplish this, without inheritance of the superior class to the new class. Any suggestions?
Max
Related
What would be the best practice to create a new object, which uses the attributes of an existing object of another class type in Python?
Let's say I have an object MvsObject of the class MvsClass and I want to create a new object of a different class that uses the attributes densePointClouds and sparsePointClouds and processes them with the methods of the class PointCloud.
Would the following approach be a "good practice" in Python?
class PointCloud:
def __init__(self, MvsObject):
self.densePointClouds = MvsObject.densePointClouds
self.sparsePointClouds = MvsObject.sparsePointClouds
Your solution is good. You could also use #classmethod decorator in order to define two ways to build your class (in a "classical" way, or using another instance).
class PointCloud:
def __init__(self, dense_points_cloud, sparse_points_cloud):
self.dense_points_cloud = dense_points_cloud
self.sparse_points_cloud = sparse_points_cloud
#classmethod
def from_mvs_object(cls, mvs_object):
return cls(mvs_object.dense_points_cloud, mvs_object.sparse_points_cloud)
You would instantiate it like this:
point = PointCloud.from_mvs_object(mvs_object)
Note also I renamed the attributes because using Python, it's preferred to use snake case to name your variables.
So I basically put this question for some advice
I have few classes which basically does some pandas operations and return a dataframe. But these dataframes needs addition and subtraction on some filter options. I planned to write a class to override __add__ and __sub__ methods, so that these dataframes are added or subtracted by my code which implements those filters. Below is a basic structure
import ArithOperation
class A:
def dataA(self, filenameA):
dfa = pd.read_excel(filenameA)
return ArithOperation(dfA)
class B:
def dataB(self, filenameB):
dfb = pd.read_excel(filenameB)
return ArithOperation(dfB)
dfA and dfB here are pandas dataframes.
class ArithOperation:
def __init__(self, df):
self.df = df
def __add__(self, other):
# here the filtering and manual addition is done
return ArithOperation(sumdf)
def __sub__(self, other):
# here the filtering and manual subtraction is done
return ArithOperation(deltadf)
Basically I do the calculation as below
dfa = A().dataA()
dfb = B().dataB()
sumdf = dfa+dfb
deltadf = dfa-dfb
But how do I make the sumdf and deltadf have default dataframe functions too. I know I should inherit dataframe class to ArithOperation but I am confused and bit uncomfortable of instantiating ArithOperation() at many places.
Is there a better design pattern for this problem?
Which class to inherit on ArithOperation so that I have all pandas dataframe functions too on ArithOperation object ?
It looks to me you want to customize the behaviour of an existent type (dataframes in this case, but it could be any type). Usually we want to alter some of the behaviour to a different one, or we want to extend that behaviour, or we want to do both. When I say behaviour think methods).
You can also choose between a has-a approach (that is wrapping an object, by creating a new class whose objects hold a reference to the original object. That way you can create several new, different or similar methods that make new things, eventually using some of the existing ones, by using the stored reference to invoke original methods. This way you kind of adapt the original class interface to a different one. This is known as a wrapper pattern (or adapter pattern).
That is what you have made. But then you face a problem: how do you accept all of the possible methods of the original class? You will have to rewrite all the possible methods (not pratical), just to delegate them on the original class, or you find a way of delegating them all except the few ones you override. I will not cover this last possibility, because you have inheritance at your disposal and that makes things like that quite straightforward.
Just inherit from the original class and you'll be able to create objects with the same behaviour as the parent class. If you need new data members, override __init__ and add those but don't forget to invoke the parent's class __init__, otherwise the object won't initialize properly. That's where you use super().__init__() like described below. If you want to add new methods, just add the usual defs to your child class. If you want to extend existant methods, do as described for the __init__ method. If you want to completely override a method just write your version with a def with the same name of the original.method, it will totally replace the original.
So in your case you want to inherit from dataframe class, you'll have to either choose if you need a custom __init__ or not. If you need define one but do not forget to call the parent's original inside it. Then define your custom methods, say a new __add__ and __sub__, that either replace or extend the original ones (with the same technique).
Be careful in not defining methods that you think are new, but actually existed in the original class, cause they will be overriden. This is an small inconvenience of inheriting, specially if the original has an interface with lots of methods.
Use super() to extend a parent's class behaviour
class A:
pass # has some original __init__
class B(A): # B inherits A
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # preserves parent initialization, passing the same received arguments. If you don't do this parent __init__ will be overrided, not initialising parent object properly.
# add your custom code
pass
The thing with super() is that it solves some problems that arise when using multiple inheritance (inherit from several classes), when determining which of the parents method should be called, if you have several with the same named method; it is recommended over calling the parent's method with SomeParentClass.method() inside the child class.
Also if you subclass a type because you need it, you shouldn't be afraid of using it "everywhere" as you said. Make sure you customize it for a good reason (so think if making this to dataframes is appropriate, or is there another simpler way of achieving the same objective without doing that; can't advise you here, I haven't experience with pandas), then use it instead of the original class.
My lecturer wrote some code and I have no idea how to read it and google isn't helping, can someone please clarify how this code interacts.
yield Arc(tail_node, head = tail_node - 1, label="1down", cost=1)
Is the method call for the class
class Arc(namedtuple('Arc', 'tail, head, label, cost')):
The class Arc contains no methods, and no __init. I have no clue how these two are interacting since I thought class parameters accepted another class, and it made the current class a subclass or abstract etc.
The collections.namedtuple function is a class factory. It takes some parameters and returns a class. The class inherits from tuple, but its values are also accessible by name as attributes (not only by index).
The Arc class you show uses namedtuple to create its base class. You could equivalently write it with separate statements, giving the base class it's own name:
Base = namedtuple('Arc', 'tail, head, label, cost') # this creates a class
class Arc(Base): # this class inherits from the base class
pass
If the Arc class doesn't have any methods of its own, there wouldn't be much point in defining it at all (you'd just use the name Arc instead of Base for the class returned from namedtuple). I'm guessing there is some more code in the Arc class, just not anything relevant to your question. The behavior inherited from the base class is enough to create instances using positional or keyword arguments, so the yield statement you show doesn't need any additional code.
What is method overriding? What is the exact need or use of method overriding? An example with a python code will be more useful.
class Car(object):
def shifting(self):
return "manual"
class AutoCar(Car):
def shifting(self):
return "automatic"
autos = [Car(), AutoCar()]
for auto in autos:
print(auto.shifting())
In this basic example AutoCar has overriden the method shifting of the base class.
Were you to receive a list with a mix of unknown Cars (Manual and Automatic) you can query the shifting method and find out.
Of course given Python is dynamically typed, the list could contain instances from other class types which also have a shifting method. But it's not the point.
Output:
manual
automatic
Let's say I've got python object A, that is an instance of class A. Every instance of class A has an attribute SubType.
I've also got classes SubType_B, SubType_C, and SubType_D, each of which has a method called ingest(). The ingest() method was previously using (self) to get all the parameters it needed, but that self is now the instance of class A.
What is the most elegant way to inherit / use the method ingest() from a SubType class (e.g. SubType_A), using the self from object A?
Previously, the ingest() method was defined in class A, but I would like to break that out into separate classes. Class A is instantiated, and based on the SubType parameter, that object would inherit the correct ingest() method from the corresponding SubType class.
In real simple terms, I'd like one object to grab a method from another object, as if it were its own.
UPDATE
Final solution was to make a factory function that returns instances of the SubType classes. This factory reads information in parameters passed to it, that determine which SubType class to instantiate. The SubType classes all extend Class A.
I had envisioned things backwards, thinking I started with the most general class, then incorporated attributes and methods from sub-classes. This factory-like-function does the requisite information gathering, then instantiates the appropriate sub-class.
Thanks to #HenryGomersall and #IgnacioVazquez-Abrams for ideas and clarification.