Python classes: How should a built it - python

I am trying to create a class called ListenerVilma that has two methods: "Clock_" and "Diagnostics_". Nevertheless both methods will call inner functions. The following code shows my attempt to achieve the mentioned behavior, but when I call ListenerVilma.Clock_() the get the following error:
TypeError: unbound method Clock_() must be called with ListenerVilma instance as first argument (got nothing instead)
How should a create my class ListenerVilma???
Thanks.
#!/usr/bin/env python
import rospy
from rosgraph_msgs.msg import Clock
from diagnostic_msgs.msg import DiagnosticArray
class ListenerVilma:
"""Class that listens all topics of the file vilmafeagri"""
def Clock_(self):
"""Method that listens the topic /clock if the file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
def Diagnostics_(self):
"""Method that listen the topic /diagnostics from rosbag file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, diagnostics):
print diagnostics
def listener(self):
rospy.Subscriber('diagnostics', DiagnosticArray, self.callback)
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
ListenerVilma.Clock_()
rospy.spin()

the error is in line 41 in ListenerVilma.Clock_() here your directly using the method of your class so no implicit argument is pass and a instance of ListenerVilma is expected. The solution is ListenerVilma().Clock_() this first create a instance of your class and from say instance call its Clock_ method.
Outside that, your class construction is very weird, the __init__ is used to initialize a class and a basic class construction is like this
class Foo:
"""example class"""
def __init__(self,*argv,**karg):
"""initialize this class"""
#do something with argv and/or karg according to the needs
#for example this
print "init argv", argv
print "init karg", karg
self.ultimate=42
def do_stuff(self):
"""this method do something"""
print "I am doing some stuff"
print "after 7.5 million years of calculations The Answer to the Ultimate Question of Life, the Universe, and Everything is: ", self.ultimate
def do_some_other_stuff(self,*argv,**karv):
"""this method do something else"""
print "method argv", argv
print "method karg", karg
# basic usage
test = Foo(1,2,3,key_test=23)
test.do_stuff()
test.do_some_other_stuff(7,8,9,something=32)
test.ultimate = 420
test.do_stuff()
I am not quite sure what you intentions are, but you build Clock_ and Diagnostics_ as a class, but they are not, and as right now they do nothing, if you want they to be class on their own do
class Clock_:
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
and the same with Diagnostics_, and I don't see a reason to the listener method so I would put what it does in the __init__, but maybe the rospy need it? I don't know, but for the looks of it then it should be used as
rospy.init_node('listener', anonymous=True)
Clock_()
Diagnostics_()
rospy.spin()

The Clock_ method doesn't belong to the class; it's an 'instance' method.
There are two options
In the main function: create an instance of ListenerVilma: listener = ListenerVilma(), or
In the ListenerVilma class: annotate the methods with #classmethod and make the class inherit from object: class ListenerVilma(object):. But remember, the first argument in your methods will be a reference to the class and not a reference to an instance.

The following code performs better the behavior that I wanted. :)
class ListenerVilma:
def CLOCK(self):
def clock_sub():
rospy.Subscriber('clock', Clock, clock_callback)
def clock_callback(clock):
print clock
clock_sub()
def DIAGNOSTICS(self):
def diagnostics_sub():
rospy.Subscriber('diagnostics', DiagnosticArray, diagnostics_callback)
def diagnostics_callback(diagnostics):
print diagnostics
diagnostics_sub()
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
myVilma = ListenerVilma()
myVilma.CLOCK()
myVilma.DIAGNOSTICS()
rospy.spin()

Related

Passing class objects to another class method Python

I am trying to understand where my mistake lies and I was hoping you could please help me.
I have this code:
import copy
class FooInd():
def __init__(self):
self.a=1
class Planning():
def foo(self,pop):
print(pop.a)
def main():
ind=FooInd()
Planning.foo(copy.deepcopy(ind))
if __name__ == "__main__":
Planning.main()
However I keep receiving this error:
Planning.foo(copy.deepcopy(ind))
TypeError: foo() missing 1 required positional argument: 'pop'
I believe that the mistake is not in the foo method definition, but in my class initiation of the FooInd, however I have checked the Python documentation for classes and I could not find a solution.
Does anyone have a clue of what could I try or where can I check?
Many thanks in advance!
You call Planning.foo on the class, not an instance of the class. You provided the second argument it requires, but not the self argument.
You have two choices:
Construct a Planning instance to call foo on:
def main():
ind=FooInd()
Planning().foo(copy.deepcopy(ind))
# ^^ Makes simple instance to call on
Make foo a classmethod or staticmethod that doesn't require an instance for self:
class Planning():
#staticmethod # Doesn't need self at all
def foo(pop):
print(pop.a)
I think you meant to instantiate Planning before calling methods on it:
import copy
class FooInd():
def __init__(self):
self.a = 1
class Planning():
def foo(self, pop):
print(pop.a)
def main(self):
ind = FooInd()
self.foo(copy.deepcopy(ind))
if __name__ == "__main__":
p = Planning()
p.main()
Output:
1

How to import function into a class from external file?

I am coding a simple game of tic-tac-toe. My function to check winning is too repetitive and big, so I want to put it into an external file. My idea is:
class Game(object):
def __init__(self):
pass
import funcFile
instance = Game()
instance.func()
While in funcFile.py is:
def func():
print("Hello world!")
But:
Traceback (most recent call last):
instance.func()
TypeError: 'module' object is not callable
Is there a way to do this, or should I put everything in one file?
There are many ways to solve this kind of problem.
The most straightforward solution (which is what I think you had in mind) is to factor out the implementation of the func method to a separate module. But you still need to define the method in the class.
main.py:
from func_module import func_implementation
class Game: # note: you don't need (object)
def __init__(self):
pass
def func(self):
return func_implementation()
instance = Game()
instance.func()
func_module.py:
def func_implementation():
print('hello')
Another approach would be to factor out the func method to another class which the Game class inherits. This pattern is also known as a mixin class:
main.py:
from func_module import FuncMixin
class Game(FuncMixin):
def __init__(self):
pass
instance = Game()
instance.func()
func_module.py:
class FuncMixin:
def func(self):
print('hello')
But this is less clear, as you can't immediately see that the Game class has a func method and what it does. Also you can introduce subtle bugs with multiple inheritance if you're not careful. So in your case I'd prefer the first approach.
You should try from funcFile import func in your main file:
from funcFile import func
class Game(object):
def __init__(self):
pass
import funcFile
instance = Game()
instance.func()

Error "listed is not defined" in a Python class

Why do I get the error listed is not defined in the following code snippet?
import socket,select
from threading import *
import time
neighbours=[]
def neighbourfuncall():
print('In neighbours')
class pyserver(Thread):
dictn={}
HOST=socket.gethostname()
PORT=8888
buf=1024
ADDR=(HOST,PORT)
listed=[]
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.bind(ADDR)
sock.listen(30)
def __init__(self):
self.interval=6
listed.append(sock)
thread=threading.Thread(target=neighbourfuncall,args=())
thread.daemon=True
thread.start()
def run(self):
while True:
sel,out,spl=select.select(listed,[],[],15.0)
for s in sel:
if s==sock:
client,address=sock.accept()
listed.append(client)
dest=client.recv(buf)
dictn[client]=dest
else:
pass
serv=pyserver()
serv.run()
You have to access listed with the following syntax:
pyserver.listed = ["I need to study more Python!"]
since it's a static class variable.
As you're in a class, you need to use self.list.append(smth). All class variables must be accessed using self.
By the way, socket operations must be in __init__(). You'd better do this:
def __init__(self):
self.smth=socket()
self.other=[]
self.smth.DoSomething()
def Hello(self):
self.other.append("Hello") #just example

How to kill a subprocess initiated by a different function in the same class

I want to kill a process from another function in the class attending to the fact that it was initiated by another function. Here's an example:
import time
class foo_class:
global foo_global
def foo_start(self):
import subprocess
self.foo_global =subprocess.Popen(['a daemon service'])
def foo_stop(self):
self.foo_start.foo_global.kill()
self.foo_start.foo_global.wait()
foo_class().foo_start()
time.sleep(5)
foo_class().foo_stop()
How should I define foo_stop?
jterrace code works. If you don't want it to start when you initialize, just call Popen in a separate function and pass nothing to the init function
import subprocess
import time
class foo_class(object):
def __init__(self):
pass
def start(self):
self.foo = subprocess.Popen(['a daemon service'])
def stop(self):
self.foo.kill()
self.foo.wait() #don't know if this is necessary?
def restart(self):
self.start()
foo = foo_class()
foo.start()
time.sleep(5)
foo.stop()
I'm guessing you want something like this:
import subprocess
import time
class foo_class(object):
def __init__(self):
self.foo = None
def start(self):
self.stop()
self.foo = subprocess.Popen(['a daemon service'])
self.foo.start()
def stop(self):
if self.foo:
self.foo.kill()
self.foo.wait()
self.foo = None
foo = foo_class()
foo.start()
time.sleep(5)
foo.stop()
Some things I've changed:
Imports should generally go at the top of the file.
Classes should inherit from object.
You want to use an instance variable.
It doesn't make much sense for your class's method names to start with the class name.
You were creating a new instance of foo_class when calling its methods. Instead, you want to create a single instance and calls the methods on it.

Does PyQT4 signal.connect keep objects live?

If I have a signal and I register an objects function to the signal will this keep the object live and stop the garbage collection of that object?
E.g.
class Signals():
signal = Qt.pyqtSignal()
def __init__(self):
QObject.__init__(self)
class Test();
def __init__(self, s):
s.connect(self.done)
def done(self):
print("Done")
s = Signals()
t = Test(s.signal)
t = None
s.signal.emit()
Will the Test objecct still get the signal?
No, it won't, it's not enough to keep the object alive. Just try it:
from PyQt4.QtCore import *
app = QCoreApplication([])
class Signals(QObject):
signal = pyqtSignal()
def __init__(self):
QObject.__init__(self)
class Test():
def __init__(self, s):
s.connect(self.done)
def done(self):
print("Done")
s = Signals()
t = Test(s.signal)
print("first")
s.signal.emit()
app.processEvents()
t = None
print("second")
s.signal.emit()
app.processEvents()
Output:
first
Done
second
This behaviour only applies when connecting a signal to a bound method. As an example, if you use:
s.connect(lambda: self.done())
instead, then it will work. If the library wouldn't keep a strong reference here, then you could never connect an anonymous function to a signal. So in this case pyqt has to ensure that it keeps a reference to the function, and the object (self) keeps to be referenced in the closure of the lambda.

Categories

Resources