How to inherit class instance's state from constructor argument? - python

I would like to share a state of an instance to multiple children, so they share the parent's state together.
This is a working example:
class Stack:
def __init__(self):
self.myValues = []
def my_add(self, x):
self.myValues.append(x)
class Worker(Stack):
def __init__(self, my_stack):
super().__init__()
if __name__ == "__main__":
mystack = Stack()
worker1 = Worker(mystack)
worker2 = Worker(mystack)
worker1.my_add(4)
worker2.my_add(5)
print(len(mystack.myValues))
print(len(worker1.myValues))
print(len(worker2.myValues))
Output:
0
1
1
I need the output to be "2 2 2", so share the instance and state of mystack to worker1 and worker2 without self.mystack=mystack in the constructor of class Worker.

Your Worker class ignores the Stack instance passed to it. This isn't a job for inheritance. Instances of Worker use an instance of Stack; they should not themselves be instances of Stack.
class Stack:
def __init__(self):
self.myValues = []
def my_add(self, x):
self.myValues.append(x)
class Worker:
def __init__(self, my_stack):
self.stack = my_stack
def my_add(self, x):
self.stack.my_add(x)
#property
def myValues(self):
return self.stack.myValues

Related

How to communicate between sibling objects in Python, when using Composition, not Inheritance

I have a parent object which is composed of 2 (different) child objects.
The 2 child instances need to communicate. For example, assume child1 needs to send something to child2:
import children
class Parent:
def __init__(self):
self.child1 = children.Child1(self.q)
self.child2 = children.Child2(self.q)
parent = Parent()
parent.child1.send("string")
Is there a recommended pattern to achieve this?
The best I could come up with was to create a Queue between the 2 objects. This works, but it requires the receiving object to run a thread. For example:
parent.py:
import children
import queue
import time
class Parent:
def __init__(self):
self.q = queue.Queue()
self.child1 = children.Child1(self.q)
self.child2 = children.Child2(self.q)
parent = Parent()
parent.child1.send("string")
time.sleep(1)
children.py:
import threading
class Child1:
def __init__(self, q):
self.q = q
def send(self, item):
self.q.put(item)
class Child2:
def __init__(self, q):
self.q = q
self.receiver = threading.Thread(target=self.worker, daemon=True).start()
def worker(self):
"""Process the queue"""
while True:
item = self.q.get()
print(f"{item} received")
In practice, the "items" I send in the queue are a function name and an argument list. This is basically the Command pattern as described here. But I don't like the need for receiver threads.
I would prefer if it was possible to allow one object to directly call a method in the other object.
If there was an inheritance relationship between them, with a common parent, I could maybe use super() for this:
class Child1:
def send(self, function, arguments):
super().child2.function(arguments)
But there is no inheritance in my case: just composition.
Is there a better way?
Just construct the children with a reference back to the parent:
class Child1:
def __init__(self, parent):
self.parent = parent
def send(self, msg):
self.parent.child2.print_out(msg)
class Child2:
def __init__(self, parent):
self.parent = parent
def print_out(self, msg):
print(msg)
class Parent:
def __init__(self):
self.child1 = Child1(self)
self.child2 = Child2(self)
parent = Parent()
parent.child1.send("foo")
I believe what you're looking for is the Façade Pattern.
Presumably, Parent is more than just a namespace; it knows things and does stuff. Having Child1 send something to Child2 seems like it would be a behaviour of Parent, the implementation of which is abstracted away, hidden behind the façade.
class Foo:
def send_msg(self):
return f'This is a message sent from {self.__class__.__name__}.'
class Bar:
def receive_msg(self, msg):
print(self.__class__.__name__, 'has received the following message:'
print('\t', msg)
class Facade:
def __init__(self):
self.foo = Foo()
self.bar = Bar()
def foo_the_bar(self):
self.bar.receive_msg(self.foo.send_msg())
>>> facade = Facade()
>>> facade.foo_the_bar()
Bar has received the following message:
This is a message sent from Foo.

Most pythonic way to super parent class and pass class variables

I have a parent class and a child class. The parent class needs some predefined class variables to run call(). The objects are not defined in the child class.
Question: What is the most pythonic way to pass the variables when calling super() without changing the parent class.
Example:
class Parent:
def __init__(self):
self.my_var = 0
def call(self):
return self.my_var + 1
class Child(Parent):
def __init__(self):
self.different_var = 1
def call(self):
my_var = 0
super().__call__() # What is the most pythonic way of performing this line
I know I could just make my_var in the child class a class object and it would work, but there must be a better. If not that would be an acceptable answer as well.
Your version is just a mixin. You have to __init__ the super.
class Parent:
def __init__(self):
self.my_var = 0
def call(self):
return self.my_var + 1
class Child(Parent):
def __init__(self):
super().__init__() #init super
self.different_var = 1
def call(self):
self.my_var = 50
return super().call() #return call() from super
c = Child()
print(c.call()) #51

How to pass all class variables from a parent *instance* to a child class?

Here's an example of what I'm trying to do:
class Parent():
def __init__():
self.parent_var = 'ABCD'
x = Child(self) # self would be passing this parent instance
class Child():
def __init__(<some code to pass parent>):
print(self.parent_var)
foo = Parent()
Now I know what you're thinking, why not just pass parent_var itself to the child instance? Well my actual implementation has over 20 class variables in Parent. I don't want to have to manually pass each variable to the __init__ of the Child instance that's instantiated in Parent-- is there a way to make all Parent class variables available to Child?
EDIT - SOLVED:
This is the way I found that works:
class Parent():
def __init__(self):
self.parent_var = 'ABCD' # but there are 20+ class vars in this class, not just one
x = Child(self) # pass this parent instance to child
class Child():
def __init__(self, parent):
for key, val in vars(parent).items():
setattr(self, key, val)
print(self.parent_var) # successfully prints ABCD
foo = Parent()
If you inherit from the parent class all variables will be present in child classes. Use super init in the child to make sure the parent class instantiates.
class Parent:
def __init__(self):
self.parent_var = 'ABCD'
class Child(Parent):
def __init__(self):
super().__init__()
child = Child()
print(child.parent_var)
prints:
'ABCD'
You would pass the instance of Parent like you would any value.
class Parent:
def __init__(self):
self.parent_var = 'ABCD'
x = Child(self)
class Child:
def __init__(self, obj):
print(obj.parent_var)
Found a solution and wanted to post the answer in case anyone who finds this needs it:
class Parent():
def __init__(self):
self.parent_var = "ABCD" # just an example
x = Child(self) # pass this parent instance (this object) to child
class Child():
def __init__(self, parent):
# copies variables from passed-in object to this object
for key, val in vars(parent).items():
setattr(self, key, val)
print(self.parent_var) # successfully prints ABCD
foo = Parent()

Using Python how can I have multiple class instances with their own objects as members?

I am trying to have two objects of the same class have their own object as a member...when I call a function of their individual classes, that function is being called from both top-objects...
like this...
class Operation(threading._Timer):
def __init__(self):
threading._Timer.__init__(self)
def cancel(self):
self.finished.set()
class Manager():
def __init__(self):
self.ops = Operation()
def stop(self):
self.ops.cancel()
class A(object):
def __init__(self):
self.ClassManager = Manager()
instance1 = A()
instance2 = A()
instance1.ClassManager.stop()
#
When I call instance1.ClassManager.stop(), it also stops the instance2's Manager.Operation....
I've looked around and only found that if your class has __init__(self): with its members defined with the self tag, they should be individualized for that particular instance of the class...
Thanks

Is it instance? or a class? python paradox

def F(thing):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco():
return "Deco:" + self.inst.who()
return C
class worker(object):
def who(self):
return "I am a worker"
worker = F(worker)
w = worker()
print(w.deco())
Question: what prototype does the function F return(what is "C" when F() return C)? Is it a instance(object)? or a class?
It looked like what F(worker) return is a class, instead of an instance.
The reason is Because if it is an instance, then worker = F(worker) is also an instance, yes?
Then when calling for the instance: w = worker(), we need a __call__ function in the decorator, C, otherwise we cannot call it. But actually we don't have __call__ here, so it looked like it is a class.
If you admit it , then please look at the following:
class F(object):
def __init__(self, anything):
self.anything = anything
def __call__(self):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco():
return "Deco:" + self.inst.who()
return C(self.anything())
class worker(object):
def who(self):
return "I am a worker"
worker = F(worker)
w = worker()
print(w.deco())
Now, tell me what is the prototype of worker = F(worker) now? In principle, no matter what F() is, it should not affect the prototype of worker, right?
Then "worker"(not worker()) here should be a class, as usual(as we deduced in the first case). But in this case, it is not! because when we call worker = F(worker), for F is a class, then it will initiating an instance by calling __init__! Then now worker is the instance!
Your code doesn't even work as is. If you fix your code to actually be valid python, then for your first question, F returns a class, C which gets instantiated when you say w = worker()
def F(thing):
class C(object):
def __init__(self):
self.inst = thing()
def deco(self):
return "Deco:" + self.inst.who()
return C
class Worker(object):
def who(self):
return "I am a worker"
worker = F(Worker)
print(worker)
w = worker()
print(w)
print(w.deco())
You would get
<class '__main__.C'>
<__main__.C object at 0x2471e4>
Deco:I am a worker
For the second question, F is creating an instance of itself and when you call that instance, it returns an instance of class C.
class F(object):
def __init__(self, anything):
self.anything = anything
def __call__(self):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco(self):
return "Deco:" + self.inst.who()
return C(self.anything)
class Worker(object):
def who(self):
return "I am a worker too"
worker = F(Worker)
print(worker)
w = worker()
print(w)
print(w.deco())
and you would get
<__main__.F object at 0x243444>
<__main__.C object at 0x243b0c>
Deco:I am a worker too

Categories

Resources