2016-11-03 23 views
5

С PyQt5, оба они возвращают объект приложения:qApp против QApplication.instance()

app = QtWidgets.QApplication.instance() 
app = QtWidgets.qApp 
for i in app.arguments()[1:]: 
    ... 

Но почему print(QtWidgets.QApplication.instance() is QtWidgets.qApp) печать False?

ответ

13

Разница между QtWidgets.QApplication.instance() и QtWidgets.qApp, что последний является переменной статический модуль, который должен быть создан, когда модуль первого импорта. Это приводит к следующему первоначально затруднительного поведения:

>>> from PyQt5 import QtWidgets 
>>> inst = QtWidgets.QApplication.instance() 
>>> qapp = QtWidgets.qApp 
>>> (inst, qapp) 
(None, <PyQt5.QtWidgets.QApplication object at 0x7ff3c8bd3948>) 

Так что даже если не QApplication объект был создан еще, переменная qApp все еще указывает на QApplication инстанции. Если модули были больше похожими на классы, так что они могли бы иметь динамические свойства, было бы возможно, что qApp будет работать точно так же, как QApplication.instance() и первоначально возвращает None. Но поскольку он является статическим, он должен всегда возвращать объект правильного типа, чтобы впоследствии он мог ссылаться на тот же базовый объект C++, что и QApplication.instance().

Однако, важно отметить, что qApp изначально просто пустой обертка:

>>> qapp.objectName() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: wrapped C/C++ object of type QApplication has been deleted 

После QApplication создается, хотя, они оба указывают на одно и то же:

>>> app = QtWidgets.QApplication([]) 
>>> app.setObjectName('foo') 
>>> qapp.objectName() 
'foo' 

Итак, причина, по которой (QtWidgets.QApplication.instance() is QtWidgets.qApp) возвращает False, заключается в том, что два объекта - разные оболочки python вокруг одного и того же базового объекта C++.

Это важно знать об этой точке, если вы когда-нибудь понадобится, чтобы создать свой собственный sublass из QApplication, но все же хотите использовать qApp:

>>> from PyQt5 import QtWidgets 
>>> class MyApp(QtWidgets.QApplication): 
...  def hello(self): print('Hello World') 
... 
>>> myapp = MyApp([]) 
>>> myapp.hello() 
Hello World 
>>> 
>>> QtWidgets.qApp 
<PyQt5.QtWidgets.QApplication object at 0x7f5e42f40948> 
>>> QtWidgets.qApp.hello() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'QApplication' object has no attribute 'hello' 
>>> 
>>> inst = QtWidgets.QApplication.instance() 
>>> inst 
<__main__.MyApp object at 0x7f5e42f409d8> 
>>> inst.hello() 
Hello World 

Единственный способ обойти это явно перезаписать qApp модуль (и, очевидно, убедитесь, что это сделано до того, как оно может быть импортировано другими модулями):

>>> QtWidgets.qApp = myapp 
>>> QtWidgets.qApp.hello() 
Hello World