I'm beginner. Here is my code:
class Queue:
def __init__(self):
self.queue = []
def dequeue(self):
self.queue.pop(O)
def enqueue(self,element):
self.queue.append(element)
q=Queue()
q.enqueue('dog')
print(q)
But! I see this:
<__main__.Queue object at 0x00A3FC10>
What is it? How to create this class than?
That is the default display representation of an instance of your class. The default is to display the class name and the address of its instance in memory. You can override __repr__ and __str__ to customize the representation:
class Queue:
def __init__(self):
self.queue = []
def dequeue(self):
return self.queue.pop(0) # probably want to return what you dequeue.
def enqueue(self,element):
self.queue.append(element)
# Customize debug representation...you want to know it is a Queue and what is in it.
def __repr__(self):
return f'Queue({self.queue})'
# Customize print representation...may just want to see the list.
def __str__(self):
return f'{self.queue}'
q=Queue()
q.enqueue('dog')
q.enqueue('cat')
print(repr(q))
print(q)
print(f'popped {q.dequeue()}')
print(q)
Output:
Queue(['dog', 'cat'])
['dog', 'cat']
popped dog
['cat']
Related
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
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.
Let's say I want to implement some list class in python with extra structure, like a new constructor. I wrote:
import random
class Lis(list):
def __init__(self, n):
self = []
for i in range(n):
self.append(random.randint(0, 30))
Now doing Lis(3) gives me an empty list. I don't know where I did it wrong.
You are overriding the object with self = []
try the following
import random
class Lis(list):
def __init__(self, n):
for i in range(n):
self.append(random.randint(0, 30))
if you want to return a list from object call
class MyClass(object):
def __init__(self):
print "never called in this case"
def __new__(cls):
return [1,2,3]
obj = MyClass()
print(obj)
How to return a value from __init__ in Python?
or if you want an modified object try:
class MyClass:
def __getitem__(self, key):
not_self = []
for i in range(n):
not_self.append(random.randint(0, 30))
return not_self
myobj = MyClass()
myobj[3] #Output: 6
How to override the [] operator in Python?
I am not sure if using self like you did is healthy.
The program I am creating should run a queue class however errors occur that append is not able to be used in the class as it does not exist, even thought it is set to a string. Could someone help me understand why I am receiving these errors?
class Queue:
def queue(self):
self.queue = []
self.out_stack = []
def enqueue(self, other='string'):
self.enqeue = self.queue.append(other)
def dequeue(self):
if not self.out_stack:
while self.queue:
self.dequeue = self.out_stack.append(self.queue.pop(1))
return self.dequeue
def isEmpty(self):
return self.queue == []
When you create an instance variable self.queue, you are shadowing the method defined by def queue(self):
It looks like that method should perhaps be your __init__ method
class Queue:
def __init__(self):
self.queue = []
self.out_stack = []
def enqueue(self, other='string'):
self.queue.append(other)
def dequeue(self): # what is this method supposed to do?
if not self.out_stack:
while self.queue:
self.dequeue = self.out_stack.append(self.queue.pop(1))
return self.dequeue
def isEmpty(self):
return self.queue == []
Now there is still a similar problem with self.dequeue being used as both a method and an attribute. I am not sure what you are trying to do there.
This is probably a basic OO question:
I'm trying to do a nested console menu with cmd which has gone well.
I also want all my sub-consoles to have access to the same objects. This has not gone well.
My simple Example:
import cmd
class MainConsole(cmd.Cmd):
def __init__(self,obj1,obj2):
cmd.Cmd.__init__(self)
self.prompt = ">"
self.obj1 = obj1 # The objects I want access to in all my consoles.
self.obj2 = obj2
self.menu1 = SubConsole1() # I could pass in the objects here as arguments
self.menu2 = SubConsole2() # but there should be a better way.
def do_menu1(self,args):
self.menu1.cmdloop()
def do_menu2(self,args):
self.menu2.cmdloop()
def do_info(self,args):
self.menu1.do_info(args)
self.menu2.do_info(args)
def do_exit(self,args):
return -1
class SubConsole1(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
class SubConsole2(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "2>"
def do_action(self,args):
print obj1.someattr2 # Doesn't work
class anobject(object):
def __init__(self,init_value):
self.someattr1 = init_value
self.someattr2 = init_value * 2
object1 = anobject(1)
object2 = anobject(2)
c=MainConsole(object1,object2)
c.cmdloop()
When I run this I get
>
>menu1
1>info
AttributeError: SubConsole1 instance has no attribute 'obj1'
Try again.
>
>menu2
2>info
NameError: global name 'obj1' is not defined
I'm not sure if the SubConsoles should be sub-classes of MainConsole. I also tried nesting the SubConsoles inside of MainConsole.
EDIT Okay, I misunderstood what you're doing.
You are right, SubConsole1 and 2 do not need to inherit from MainConsole. But they should have a reference to the main console.
Something like:
class MainConsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2
The other option, and probably a better one from a design point of view, is to pull out all the objects you want to access into a Context container object, and have all the various Cmd objects maintain their own reference to that Context container.
Something like this:
import cmd
from collections import namedtuple
class MyConsole(cmd.Cmd):
def __init__(self, context):
cmd.Cmd.__init__(self)
self.context = context
class ConsoleContext(object):
def __init__(self, **kwargs):
self.__dict__ = kwargs
class MainConsole(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.menu1 = SubConsole1(context)
self.menu2 = SubConsole2(context)
self.prompt = '>'
def do_menu1(self, args):
self.menu1.cmdloop()
def do_menu2(self, args):
self.menu2.cmdloop()
def do_quit(self, args):
return True
class SubConsole1(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '1>'
def do_action(self, args):
print self.context.message1
def do_quit(self, args):
return True
class SubConsole2(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '2>'
def do_action(self, args):
print self.context.message2
def do_quit(self, args):
return True
if __name__ == '__main__':
context = ConsoleContext(message1='Message 1', message2='Message 2')
con = MainConsole(context)
con.cmdloop()
Hope I was clear enough.
You don't need multiple inheritance, but you need to give obj1 and obj2 to the inherited objects, except if you give some default values to obj1 and obj2.
class SubConsole1(MainConsole):
def __init__(self, obb1, obj2):
MainConsole.__init__(self, obj1, obj2)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
instanciated by :
sub1 = SubConsole1(object1, object2)
The other answer is correct insofar as you should not be using multiple inherritance, as the following is true:
class A(object):
pass
class B(A):
pass
class C(A):
pass
class D(B):
pass
a = A()
b = B()
c = C()
d = D()
isTrue = isinstance(a,A) and isinstance(b,A) and isinstance(c,A) and isinstance(d,A)
isTrue = isTrue and isinstance(b,B)and isinstance(d,B)
isTrue = isTrue and isinstance(c,C)
isTrue = isTrue and isinstance(d,D)
>>> print isTrue
True
It would also be wise to create a method of your main class wich creates subcmds, passing their reference to the subcmd's __init__ function. This way you have your object spawn its children more naturally.
class MainConsole(cmd.Cmd):
def spawnsubconsole(self):
return SubConsole1(self)
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2 and get the sub-cmd by running maincon.spawnsubconsole() assuming maincon is an instance of the main console class.