【发布时间】:2010-11-16 20:29:21
【问题描述】:
很简单的问题。我已经在很多地方看到它在旧式类上使用属性不应该工作,但显然 Qt 类(通过 PyQt4)不是新式的,并且在我的代码中有一些属性正在使用(据我所知,代码没有显示任何问题)
我确实遇到了一个 pyqtProperty 函数,但我似乎找不到任何关于它的文档。在这种情况下,它会是一个不错的选择吗?
【问题讨论】:
标签: python class properties pyqt
很简单的问题。我已经在很多地方看到它在旧式类上使用属性不应该工作,但显然 Qt 类(通过 PyQt4)不是新式的,并且在我的代码中有一些属性正在使用(据我所知,代码没有显示任何问题)
我确实遇到了一个 pyqtProperty 函数,但我似乎找不到任何关于它的文档。在这种情况下,它会是一个不错的选择吗?
【问题讨论】:
标签: python class properties pyqt
属性之所以有效,是因为 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 是允许使用Qt's property system,这与 Python 的不同。 Qt 属性在 Qt 的 C++ 类中是可自省的(原始 Python 属性不是),并且被 Qt 用于它们的Qt Designer 表单编辑器和Qt Creator IDE 之类的东西。它们允许对 run-time 状态进行大量内省,而这些状态在 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'>)
【讨论】: