很简单的问题。我已经在很多地方看到它在旧式类上使用属性不应该工作,但显然 Qt 类(通过 PyQt4)不是新式的,并且在我的代码中有一些属性正在使用(据我所知,代码没有显示任何问题)
我确实遇到了一个 pyqtProperty 函数,但我似乎找不到任何关于它的文档。在这种情况下它会是一个很好的选择吗?
很简单的问题。我已经在很多地方看到它在旧式类上使用属性不应该工作,但显然 Qt 类(通过 PyQt4)不是新式的,并且在我的代码中有一些属性正在使用(据我所知,代码没有显示任何问题)
我确实遇到了一个 pyqtProperty 函数,但我似乎找不到任何关于它的文档。在这种情况下它会是一个很好的选择吗?
属性有效,因为 QObject 有一个处理它们的元类。见证@quark 代码的这个小变化……:
from PyQt4.QtCore import QObject
def makec(base):
class X( base ):
def __init__(self):
self.__x = 10
def get_x(self):
print 'getting',
return self.__x
def set_x(self, x):
print 'setting', x
self.__x = x
x = property(get_x, set_x)
print 'made class of mcl', type(X), issubclass(type(X), type)
return X
class old: pass
for base in (QObject, old):
X = makec(base)
x = X()
print x.x # Should be 10
x.x = 30
print x.x # Should be 30
运行它会发出:
made class of mcl <type 'PyQt4.QtCore.pyqtWrapperType'> True
getting 10
setting 30
getting 30
made class of mcl <type 'classobj'> False
getting 10
30
看到不同?在真正是遗留(旧类型)类的类中,第二次制作的类中,元类是classobj
(它不是类型的子类)并且属性不能正常工作(分配x.x
绕过属性,然后得到x.x
也看不到该物业了)。但是在第一种情况下,Qt 情况下,有一个不同的元类,它是类型的子类(所以说这个类“不是新样式”是不正确的!),因此事情确实可以正常工作。
根据我的经验,Python 排序的属性在 PyQt4 对象上工作得很好。我不知道 PyQt4 是否明确支持它们,或者是否存在一些隐藏的陷阱,但我从未见过它们行为不端。这是一个使用 PyQt 4.4 和 Python 2.5 的示例:
from PyQt4.QtCore import QObject
class X( QObject ):
def __init__(self):
self.__x = 10
def get_x(self):
return self.__x
def set_x(self, x):
self.__x = x
x = property(get_x, set_x)
x = X()
print x.x # Should be 10
x.x = 30
print x.x # Should be 30
pyqtProperty
是允许使用与 Python 不同的Qt 属性系统。Qt 属性可以从 Qt 的 C++ 类(原始 Python 属性不是)中进行自省,并且被 Qt 用于Qt Designer表单编辑器和Qt Creator IDE 之类的东西。它们允许对运行时进行大量的自省声明您在 Python 中拥有并在 C++ 中错过。一般来说,Qt 为 C++ 提供了一些动态语言的特性,而这并不是 PyQt 提供不止一种方法来做同样事情的唯一领域(还要考虑字符串、字典、文件 I/O 等)。对于这些选择中的大多数,我的主要建议是选择一侧或另一侧并坚持下去,以避免出现一些令人不快的不兼容的可能性。我更喜欢 Python 版本而不是 Qt 版本,因为 Python 对我的工作来说比 Qt 更核心。如果您打算考虑将任何东西从 PyQt 移植回 C++ Qt,那么您可能更喜欢 Qt 版本的功能而不是 Python 版本。
至少在 PyQt4.5 中,Qt 类肯定是新样式的对象,从它们的方法解析顺序可以看出:
from PyQt4 import QtGui
print QtGui.QWidget.__mro__
(<class 'PyQt4.QtGui.QWidget'>, <class 'PyQt4.QtCore.QObject'>, <type 'sip.wrapper'>, <class 'PyQt4.QtGui.QPaintDevice'>, <type 'sip.simplewrapper'>, <type 'object'>)