解答pyqtSignal为什么要定义在在Qthread类的init函数外

最近捣鼓pyqt,发现真的没把python学精,发现很多疑问。
在很多教程中,继承了qthread的类如果要emit一个pyqtSignal,这个pyqtSignal都定义在了这个类的init函数外,而不是作为一个属性去定义。我起初认为定义在内外没区别,直到我亲自做了实验。

class test(QThread):
    sig= QtCore.pyqtSignal()

works but

class test(QThread):
	def __init__(self):
	    self.sig= QtCore.pyqtSignal()

doesn’t work and it states something about the signal not being bound… What do I not understand here? Why does one work?

stackoverflow上找到了解答。
但在我直接给你解释前,我们不妨来探索一下python类中定义在init函数外的属性的特性。
做如下实验:

>>> class test():
...     out = 1
...
>>> print(hex(id(test.out)))
0x28540c700f0
>>> test.out
1
>>> instance1 = test()
>>> print(hex(id(instance1.out)))
0x28540c700f0
>>> instance1.out
1
>>> instance1.out += 1
>>> instance1.out
2
>>> test.out
1
>>> print(hex(id(instance1.out)))
0x28540c70110
>>>

我们发现,我们定义了一个叫test的类,这里面有一个在init外的属性out。
我们用print(hex(id(test.out)))输出这个out的内存地址,是0x28540c700f0
然后我们实例化一个out类,叫他instance1,输出instance1.out的值和内存地址,均和test.out一模一样,这里值得注意的是他们共享同一个内存地址
但当我们尝试修改这个实例instance1的out属性时,神奇的事情发生了:
这时候这个实例的out的内存地址发生改变,并且test.out的值并没有随之改变。
也就是说,在我们修改实例instance1的out属性时,这个out被python自动转化为只属于这个实例的变量。如果不修改的话,所有实例的out都共享一个内存地址。

在看一个更能说明这一现象的实验:

>>> class a:
...     o = 1
...
>>> a.o
1
>>> ins1 = a()
>>> ins2 = a()
>>> ins3 = a()
>>> ins1.o
1
>>> ins2.o
1
>>> ins3.o
1
>>> print(hex(id(a.o)))
0x215a31400f0
>>> print(hex(id(ins1.o)))
0x215a31400f0
>>> a.o += 1
>>> a.o
2
>>> ins1.o
2
>>> ins2.o
2
>>> ins3.o
2
>>> print(hex(id(ins1.o)))
0x215a3140110
>>> print(hex(id(a.o)))
0x215a3140110
>>> ins1.o += 1
>>> ins1.o
3
>>> a.o
2
>>> ins2.o
2
>>> ins3.o
2
>>> print(hex(id(ins1.o)))
0x215a3140130
>>> print(hex(id(a.o)))
0x215a3140110
>>> print(hex(id(ins2.o)))
0x215a3140110
>>> a.o = 'test'
>>> ins1.o
3
>>> ins2.o
'test'
>>> ins3.o
'test'

当我们自行修改某个实例的属性o时,这个实例的属性o就在和这个类“脱钩”,不再受这个类控制。

所以我们再回到本文探讨的问题上,为什么pyqtSignal为什么要定义在在Qthread类的init函数外。
因为当pyqtSignal定义在init外时,这个属性将会成为这个类的一个“全局变量”,所有这个类的实例的这个pyqtSignal属性都将指向同一个内存地址,即类.pyqtSignal的内存地址。pyqt具体信号槽的实现我不知道,但可想而知,如果pyqtSignal定义在init内,则每次实例化的实例的pyqtSignal都不一样,这对于pyqt的信号槽处理将异常复杂。而如果定义在init外,这个pyqtSignal所属的类不管被实例化多少次,他都拥有一个独一无二的内存地址,这对信号槽的信号接收将有巨大帮助。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
为槽函数定义一个信号用于串口有数据发回时调用,可以通过以下步骤实现: 1. 导入QtCore模块:`from PyQt5.QtCore import pyqtSignal` 2. 在定义一个信号:`serial_receive_signal = pyqtSignal(bytes)` 其中,bytes为信号传递的参数型,表示串口接收到的数据。 3. 在槽函数中调用信号:`self.serial_receive_signal.emit(data)` 其中,data为串口接收到的数据。 下面是一个示例代码,演示如何为槽函数定义一个信号用于串口有数据发回时调用: ```python from PyQt5.QtCore import pyqtSignal import serial class SerialThread(QThread): serial_receive_signal = pyqtSignal(bytes) # 定义信号 def __init__(self, port, baudrate): super().__init__() self.port = port self.baudrate = baudrate self.ser = None def run(self): self.ser = serial.Serial(self.port, self.baudrate) while True: data = self.ser.read(10) # 读取10个字节的数据 self.serial_receive_signal.emit(data) # 发送信号 def stop(self): self.ser.close() class MainWindow(QMainWindow): def __init__(self): super().__init__() self.serial_thread = SerialThread("COM1", 9600) self.serial_thread.serial_receive_signal.connect(self.serial_receive_slot) # 连接信号与槽函数 self.serial_thread.start() def serial_receive_slot(self, data): print(data) # 打印接收到的数据 def closeEvent(self, event): self.serial_thread.stop() super().closeEvent(event) ``` 运行以上代码后,每当串口有数据发回时,都会调用serial_receive_slot函数,并通过信号传递接收到的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值