解答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所属的类不管被实例化多少次,他都拥有一个独一无二的内存地址,这对信号槽的信号接收将有巨大帮助。

猜你喜欢

转载自blog.csdn.net/weixin_45518621/article/details/130391300