How to use method results from one class in another - python

Im just learning about classes in python and I would
like to know how results from a method in one class can
be used in a another class..here is the scenario.
Class A:
def x(self):
#do stuff and call Class B
Class B:
def y(self):
#do stuff get results and pass results to Class A
results
How can results be passed back to Class A ?
Thanks

maybe you want this
class A:
def x(self):
#do stuff and call Class B
n = 1
n += B().y() #Instance B and call y method
print n
class B:
def y(self):
#do stuff get results and pass results to Class A
x = 10
return x
a = A() #create a object with type A
a.x() #call x method of A class

Class A:
def x(self):
#do stuff and call Class B
my_B = B()
theResult = my_B.y() # you just called B's function y()
Class B:
def y(self):
#do stuff get results and pass results to Class A
return results

Assuming you create class B within the method A.x:
Class A:
def x(self):
#do stuff and call Class B
results = B().y()
Class B:
def y(self):
#do stuff get results and pass results to Class A
return results
Assuming method A.x gets the object of class B:
Class A:
def x(self, b):
#do stuff and call Class B
results = b.y()
Class B:
def y(self):
#do stuff get results and pass results to Class A
return results

Related

Can we pass the class object inside its own method?

I have a class A object method which uses another class B object's method, which the argument is class A object.
class A():
def calculate(self):
B = B.calculator(A)
class B():
def calculator(self, A):
...do something with A.attributes
It is possible to just pass attributes into the object, but I would see this possibility as the last priority. I am definitely a bit oversimplify my case, but I am wondering if there is a way to pass the entire class
Edit:
Sorry for the confusion. At the end I am trying to call class A object and A.calculate(), which will call class B obj and calculator function.
class A():
def __init__(self, value):
self.value = value
def calculate(self):
Bobj = B()
Bobj.calculator(A)
class B():
def calculator(self, A):
...do something with A.value
def main():
Aobj = A(value)
Aobj.calculate()
Your scenario does not currently indicate that you want to use any information from B when calculating A. There are a few ways of getting the functionality that you want.
Scenario: B stores no information and performs calculation. B should be a function
def B(value):
```do something with value```
return
class A():
def __init__(self, value):
self.value = value
def calculate(self):
return B(self.value)
def main():
Aobj = A(value)
Aobj.calculate()
Scenario: B stores some other information, but internal B information is not needed for the calculation. B should have a static method
class B():
#staticmethod
def calculate(value):
```do something with value```
return
class A():
def __init__(self, value):
self.value = value
def calculate(self):
return B.calculate(self.value)
def main():
Aobj = A(value)
Aobj.calculate()

Limit of decorator as class compared to decorator as function

I want to make sure that I understood correctly how decorator as class works.
Let's say i have a decorator as a function that add an attribute to an object
def addx(obj):
obj.x = 10
return obj
#addx
class A:
pass
assert A.x == 10
Is it possible to write the same decorator as a class decorator? since the class decorator can't return the object itself with __init__
class addx:
def __init__(self, obj):
obj.x = 10
# ???
You could write an equivalent class-based decorator like this...
class addx:
def __new__(self, obj):
obj.x = 10
return obj
#addx
class A:
pass
assert A.x == 10
...but I don't think this really gets you anything. The utility of a class-based decorator becomes more apparent when your goal is to modify objects of class A, rather than class A itself. Compare the following two decorators, one function based and one class based:
def addx_func(kls):
def wrapper():
res = kls()
res.x = 10
return res
return wrapper
class addx_class:
def __init__(self, kls):
self.kls = kls
def __call__(self):
res = self.kls()
res.x = 10
return res
#addx_func
class A:
pass
#addx_class
class B:
pass
a = A()
assert a.x == 10
b = B()
assert b.x == 10

Calling different parent-class methods with one decorator

So basically my problem seems like this.
class A():
def func(self):
return 3
class B():
def func(self):
return 4
class AA(A):
def func(self):
return super(AA, self).func
class BB(B):
def func(self):
return super(BB, self).func
The func function is doing some work and one of the things it does is getting some attribute(or running method or whatever) from it's parent class.
Since func originally does the same logic at both cases (except that only parent class changes) I'd like to do this with decorators.
Is it possible? if so how to do it? Do I have somehow to pass parent-class as a argument?
I'll be very grateful for answers it's been bothering me for a while now.
There is no need to use super to access data attributes of a parent class.
Neither does a class need a parent in order for access to data attributes to work.
You can use a mixin to do the job:
# A and B stay the same - they still have a c attribute
class A():
c = 3
class B():
c = 4 # I've changed B to make it clear below
#Instead have a mixin which defines func()
class Mixin:
def func(self):
# func has its behaviour here
return self.c
class AA(Mixin, A):
pass
class BB(Mixin, B):
pass
a = AA()
b = BB()
print(a.func())
print(b.func())
Output:
3
4
You could do it with a single class decorator by defining a generic method inside of it that does what you want, and then adding it to the class being decorated. Here's what I mean:
def my_decorator(cls):
def call_super_func(self):
return super(type(self), self).func()
setattr(cls, 'call_super_func', call_super_func)
return cls
class A():
def func(self):
print('in A.func')
return 3
class B():
def func(self):
print('in B.func')
return 4
#my_decorator
class AA(A):
def func(self):
print('in AA.func')
return self.call_super_func()
#my_decorator
class BB(B):
def func(self):
print('in BB.func')
return self.call_super_func()
aa = AA()
aa.func()
bb = BB()
bb.func()
Output:
in AA.func
in A.func
in BB.func
in B.func
Of course you could eliminate the need to do this by just defining baseclass for A and B that has a call_super_func() method in it that they would then both inherit.

Use methods of parent class A from parent class B

I have a class A:
class A(object):
def pprint(x):
print(x)
Then I have a class B:
class B(object):
def pprint(x):
x += 1
# find a way to call A.pprint(x)
Then I have a child class:
class Child(B, A):
pass
Which should be used:
child = Child()
child.pprint(1)
>>> 2
I can make changes to B but not to A. I cannot refer to A directly in B. B will never be instantiated directly, always via children class.
After the explanation - what you need is not super() you need something like sibling_super() to find the next class in the multiple inheritance chain. You can poll Python's MRO for that, for example:
class A(object):
def pprint(self, x): # just to make it valid, assuming it is valid in the real code
print(x)
class B(object):
#staticmethod
def sibling_super(cls, instance):
mro = instance.__class__.mro()
return mro[mro.index(cls) + 1]
def pprint(self, x):
x += 1
self.sibling_super(B, self).pprint(self, x)
class Child(B, A):
pass
child = Child()
child.pprint(1) # 2
You have a couple of options for accessing the A method from the B class without having B inherit from A.
First, you could create a staticmethod and call it from B.
class A(object):
#staticmethod
def pprint(x):
print(x)
class B(object):
def pprint(self, x):
print(x + 1)
A.pprint(x)
Or you could inherit A in B like this:
class A(object):
def pprint(self, x):
print(x)
class B(A):
def pprint(self, x):
print(x + 1)
super(B, self).pprint(x)
Then for your Child class only inherit from B:
class Child(B):
pass
>>> c = Child()
>>> c.pprint(1)
2
1
OK, newest solution.
import inspect
class C(B, A):
def pprint(self, x):
a_class = inspect.getmro(Child)[-2]
a_class.pprint(self, x)
Since object will be the last result in inspect.getmro(Child) we skip that one to get the one before the last one, which is A. We then call that class's pprint method. You could also, to be more sure, if you know the __name__ of the class you want to call, iterate over the results from inspect.getmro(Child) and find the one that you want.

Pythonic way to create dynamic class methods

I am wondering if the following strategy is a proper/pythonic way to create a dynamic function within a method. The goal is to have a class that can calculate a value based on a complex model defined by FUN(), but I want to be able to change that model within a script without rewriting it, or creating a bunch of different types of classes (since this function is the only thing that I expect to change).
I also read in a response to this question that the way I have it structured may end up being slower? I intend to call setupFunction() 1 to 3 times a simulation (changing the model) and call FUN many thousands of times.
Pseudocode...
class MyClass:
def __init__(self, model = 'A'):
self.setupFunction(model)
# Other Class Stuff...
def setupFunction(self, _model):
if _model == 'A':
def myFunc(x):
# Do something with x, store in result
return result
else:
def myFunc(x):
# Do something different with x
return result
self.FUN = myFunc
# Other Class Methods... some of which may call upon self.FUN
Model1 = MyClass('A')
Model2 = MyClass('B')
print(Model1.FUN(10))
print(Model2.FUN(10))
I have done some minor tests and the above seems to not break upon first glance. I know I could also do something similar by doing the following instead, but then it will have to test for the model on each call to FUN() and I will have many different model cases in the end:
class MyClass():
def __init__(self, model = 'A'):
def FUN(self, x):
if self.model == 'A':
# result = Stuff
else:
# result = Other Stuff
return result
Still new to python, so thanks for any feedback!
Not sure if I understood your question...
What about something like this?
class MyClass():
model_func = {'A' : funca, 'B' : funcb}
def __init__(self, model):
self.func = self.model_func[model]
def funca():
pass
def funcb():
pass
a = MyClass('A')
a.func()
b = MyClass('B')
b.func()
Other option might be something like this (better separation of concerns):
class Base(object):
def __new__(cls, category, *arguments, **keywords):
for subclass in Base.__subclasses__():
if subclass.category == category:
return super(cls, subclass).__new__(subclass, *arguments, **keywords)
raise Exception, 'Category not supported!'
class ChildA(Base):
category = 'A'
def __init__(self, *arguments, **keywords):
print 'Init for Category A', arguments, keywords
def func(self):
print 'func for Category A'
class ChildB(Base):
category = 'B'
def func(self):
print 'func for Category B'
if __name__ == '__main__':
a = Base('A')
a.func()
print type(a)
b = Base('B')
b.func()
print type(b)
You can use __new__, to return different subclasses:
class MyClass():
def __new__(self, model):
cls = {'A': ClassA, 'B': ClassB}[model]
return object.__new__(cls)
class ClassA(MyClass):
def func():
print("This is ClassA.func")
class ClassB(MyClass):
def func():
print("This is ClassB.func")
a = MyClass('A')
a.func()
b = MyClass('B')
b.func()

Categories