Reputation: 119
I'm trying to come to grips with why one would want to use a pyqt signal/slot instead of just calling a class method directly.
Here is a simple snippet of code that illustrates how I see it:
from PyQt4 import QtGui, QtCore
class Simple_signal(QtCore.QObject):
single_signal = QtCore.pyqtSignal()
double_signal = QtCore.pyqtSignal()
def __init__(self):
super().__init__()
# Connect one signal to one slot
self.single_signal.connect(self.handle_signal_choice1)
# Connect another signal to two slots
self.double_signal.connect(self.handle_signal_choice1)
self.double_signal.connect(self.handle_signal_choice2)
# Connect to one method
self.method = self.handle_signal_choice3
def handle_signal_choice1(self):
print("Simple_signal - CHOICE1 received")
def handle_signal_choice2(self):
print("Simple_signal - CHOICE2 received")
def handle_signal_choice3(self):
print("Simple_signal - CHOICE3 received")
if __name__ == "__main__":
simple_signal = Simple_signal()
print('Calling choice1 via single_signal')
simple_signal.single_signal.emit()
print('Calling choice1 and choice2 via double_signal')
simple_signal.double_signal.emit()
print('Calling choice3 via class method')
simple_signal.method()
One immediate advantage to signals seems to be: It's fairly easy to attach a signal to two slots. However, I could also do that with the method example without much fuss.
The method example seems to get better CPU time results (ie is faster) than the signal/slot example, but that advantage may be lost if you needed many slots to be called from one signal.
In my mind, calling the method is cleaner than messing with the signal/slot setup.
Either would work in QWidgets.
Do I need a more complex situation where signals/slots are a better choice than directly calling the method?
Thanks.
EDIT: Being curious about the time consumed in each method, I did some timeit checks.
Add these timeit lines to the code, and replace each 'print' line in the original code (ie in handle_signal_choice1) with just 'pass' so printing to the shell doesn't slow things down.
result=timeit.timeit('simple_signal.single_signal.emit()', 'from __main__ import simple_signal', number=10000)
print('Calling choice1 via single_signal')
print('timeit says : ', result)
result=timeit.timeit('simple_signal.double_signal.emit()', 'from __main__ import simple_signal', number=10000)
print('Calling choice1 and choice2 via double_signal')
print('timeit says : ', result)
result=timeit.timeit('simple_signal.method()', 'from __main__ import simple_signal', number=10000)
print('Calling choice3 via method')
print('timeit says : ', result)
This gives me the following results, which upholds my suspicion that a single method call is faster than a single signal/slot:
Now start timeit tests
Calling choice1 via single_signal
timeit says : 0.010595089312688225
Calling choice1 and choice2 via double_signal
timeit says : 0.014604222516910098
Calling choice3 via method
timeit says : 0.0016033988748859057
That's quite a big difference if you drive a socket event loop via signals/slots instead of methods. Button clicking shouldn't matter.
Upvotes: 3
Views: 3310
Reputation: 47032
The reason to use signals and slots isn't about speed, it's about loose coupling. Using signals and slots allows for better reuse. There's a nice paper that goes over the motivation and benefits. It does add some indirection, but it's well worth it, IMHO.
Upvotes: 5