I have a setup that looks something like this simplified setup:
class WorkerBee():
def __init__(self):
self.x = 1
self.old_x = None
def update_x(self, val):
self.update_old_x()
self.x = val
def _update_old_x(self):
self.old_x = self.x
class MainClass():
def __init__(self):
self.bee = WorkerBee()
def updated_WorkerBee(self):
print('yay, it was updated')
I understand the use of #property to do a get - set setup for an attribute. But in this case, I'm trying to figure out how I can directly call the WorkerBee methods (there are more than 1 in my case....) that would also trigger MainClass.updated_WorkerBee()
In:
main = MainClass()
main.bee.update_x(2)
Out:
yay, it was updated
Any help is appreciated!
You could add a reference to the main object to the bee, like a parent:
class WorkerBee:
def __init__(self, main):
self.main = main
self.x = 1
(...)
and then use it in your update methods within WorkerBee, to update main too:
def update_x(self, val):
self.update_old_x()
self.x = val
self.main.updated_WorkerBee()
To do that, pass the main to the bee when you create it:
class MainClass:
def __init__(self):
self.bee = WorkerBee(self)
Related
I have some commonfunctions that I reuse as methods of different classes. I store these function in a commonfunctions.py file inside my module directory. I would like to embed the functions inside the class where I need it, and being able to modify the attributes of the classes. I have done some attempts but none of them is practical. I was wondering what is the best approach to do that.
commonfunctions.py
def mycommonfun(self,myarg):
self.target = myarg+3
class mydummyclass(object):
def mycommonfun(self,myarg):
self.target = myarg+3
mainfile.py
import commonfunctions
class A(anotherclass):
def __init__(self):
self.target = None
# not working
commonfunctions.mycommonfun
class B(anotherclass):
def __init__(self):
self.target = None
# I can't modify self.target
self.mycommonfun = commonfunctions.mycommonfun
class C(anotherclass):
# it works but it hides all the docstring
def mycommonfun(self,myarg):
commonfunctions.mycommonfun(self,myarg)
class D(anotherclas,commonfunctions.mydummyclass):
pass #it works not sure why I have problem with hinting of the arguments
What you need to do is inherit other class methods.
commonfunction.py
class ParentClass:
def __init__(self, target):
self.target = target
def some_function(self, n):
self.target = 3 + n
mainfile.py
from commonfunction import ParentClass
class ChildClass(ParentClass):
def __init__(self, target):
super().__init__(target)
child = ChildClass(5) # self.target = 5
child.some_function(5) # self.target = 3 + 5 = 8
I have a class with methods that looks something like this
class A(object):
def __init__(self, strat):
self.strat_cls = strat
self._genInstances()
def _genInstances(self):
self.strat = self.strat_cls(self.x, self.y)
and the strat_cls:
class strat1(Strat):
def __init__(self, x=4):
self.x = x
def calculate_something(self, event):
if x > 2:
print("hello")
I initialize everything by:
example = A(strat1)
When initializing I need to be able to pass an arbitrary number of arguments to the calculate_something method in the strat1 class like this:
example = A(strat1, x=3)
or
example = A(strat1, x=3, y=5)
where y will then be used further down in the calculate_something method.
How do I do that? I need to be able to pass both "new variables" and overriding the x variable. I've tried several times using *args and **kwargs, but I end up with errors.
Here is your code with comments. The main point is you have to save the arguments in A and pass them to strat when you're initializing it.
class A(object):
def __init__(self, strat, **strat_kwargs):
self.strat_cls = strat
# save kwargs to pass to strat
self.strat_kwargs = strat_kwargs
self._genInstances()
def _genInstances(self):
# init strat with kwargs
self.strat = self.strat_cls(**self.strat_kwargs)
class strat1(Strat):
def __init__(self, x=4, y=None):
# save x and y
self.x = x
self.y = y
def calculate_something(self, event):
# use self.x here
if self.x > 2:
print("hello")
So hopefully below illustrates my point. I want to set the translate attributes once and then be able to pass any mods (like translate) into the modLevels function. The only way I know how to do this is through nested classes, but I can't figure out how to get access to the outer class points. Any ideas or maybe even let me know if I'm going about this all wrong. THANKS!
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0):
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in Outer.points: # <-- this part isnt working
p.x += self.xmove; p.y += self.ymove
def modLevels(levels, *mods):
for lev in range(levels):
for mod in mods:
mod
set1 = PointSet(...list of point objects here...)
coolMod = translate(xmove=5)
change(5, coolMod)
Pass it as a parameter.
class PointSet:
def __init__(self, points):
self.points = points
class translate:
def __init__(self, xmove=0, ymove=0, parent):
self.parent = parent
self.xmove = xmove
self.ymove = ymove
def __call__(self):
for p in self.parent.points:
p.x += self.xmove; p.y += self.ymove
Self-contained example:
class A:
def __init__(self):
self.data = [1,2,3]
class B:
def __init__(self, parent):
self.data = [4,5,6]
self.parent = parent
def access(self):
print(self.parent.data)
a = A()
b = a.B(a)
b.access()
However, as explained in comments, you don't need a nested class at all.
class PointSet:
def __init__(self, points):
self.points = points
def translate(self, x, y):
for p in self.points:
p.x += x
p.y += y
Thank you all for your help. I found a way to access the outer class on ubuntu forums. Solved referencing outer class from an inner class.
I needed to do this to pass a few parameters to the translation constructor and then overwrite the call function to use those parameters. This is a similar concept to a C++ function object like what you would pass to an STL algorithm: more on function objects.
I have two classes. a and b.
In one of class a's methods, I created an object of class b. One of class b attributes takes a function. So say I gave it a random function but does this function of class b have access to class a's attribute? even though I didn't pass it in directly as a parameter?
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self: self.counter < self.temp
return obj.attribute_function()
if __name__ == "__main__":
#pass
obj = a()
print obj.temp()
In the above example, I tried to provide a really basic example, but if you run it, it doesn't work...
Revised Code, class a should look like this:
class a:
def __init__(self):
self.temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda args: self.counter < self.temp
return obj.attribute_function(1) # i added this 1 to fill in arg
This works:
class b:
def __init__(self):
self.attribute_function = None
class a:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
obj = b()
obj.attribute_function = lambda self=self: self.counter < self._temp
return obj.attribute_function()
if __name__ == "__main__":
obj = a()
print obj.temp()
On problem you had is self.temp = 10 which shadowed your method temp().
Another problem: lambda self: self.counter < self._temp. Your lambda function was expecting an argument. But omitting self is not a good idea lambda : self.counter < self._temp, because if you call obj.attribute_function() somewhere where self is not available or has changed - it will not find self or use another self. self=self fixes that.
But generally such magic is an anti-pattern. Tell us what are your trying to achieve, and there should be a better way to do what you want. Otherwise this kind of code will ensure many headaches.
I think this is a better solution (called strategy pattern):
class B:
def __init__(self, a):
self.a = a
def temp(self):
return self.a.temp()
class A:
def __init__(self):
self._temp = 10
self.counter = 0
def temp(self):
return self.counter < self._temp
if __name__ == "__main__":
obj = B(A())
print obj.temp()
Your example does not work because you have a name collision at temp
You have assigned temp to be both a method:
def temp(self):
and an attribute:
self.temp = 10
I'm a little confused regarding using __init__ and inheritance and would love to get some help with it.
I have a class [that can not be changed]:
class A(object):
def __init__(self, param1 = 7, param2 = 10):
self.x = param1
self.y = param2
def func1(self):
op1()
op2()
def func2(self):
pass
this is some class that was written and I'm using it when overloading its functions:
class B(A):
def func1(self)
op3()
op4()
def func2(self)
op5()
My problem starts here : I want to use Class B several times and sent each time different parameter:
---new .py file: ---
def myFunction():
myInstance = B()
I want to do something like :
def myFunction():
myInstance = B(40,"test")
I thought adding to B class - __init__ but the problem is that now I'm not sure what self it would use :
explanation :
Inside B class I have overloaded func2(self)
I thought writing :
class B(A):
def __init__(self, paramNumber, paramString)
self.paramNumber = paramNumber
self.paramString = paramString
but now in func2(self) , what self is used? the new one? the old one? will it work?
meaning I will have : self.x , self.y and self.paramNumber self.parmString ?they are different "selfs"
Editing :
Should I use super as well?
class B(A):
def __init__(self, paramNumber, paramString,param1, param2)
self.paramNumber = paramNumber
self.paramString = paramString
super(B,self).__init__(param1,param2)
def myFunction():
myInstance = B(40,"test")
// I will get : self.x = 7
// self.y= 10
// self.paramNumber=40
//self.paramString = "test"
is this the correct solution?
So basically you want to run __init__ from parent class inside child:
class B(A):
def __init__(self, paramNumber, paramString):
super(B, self).__init__(param1=1, param2=2)
# the other code goes here