【问题标题】:Does using properties on an old-style python class cause problems在旧式 python 类上使用属性会导致问题吗
【发布时间】:2010-11-16 20:29:21
【问题描述】:

很简单的问题。我已经在很多地方看到它在旧式类上使用属性不应该工作,但显然 Qt 类(通过 PyQt4)不是新式的,并且在我的代码中有一些属性正在使用(据我所知,代码没有显示任何问题)

我确实遇到了一个 pyqtProperty 函数,但我似乎找不到任何关于它的文档。在这种情况下,它会是一个不错的选择吗?

【问题讨论】:

    标签: python class properties pyqt


    【解决方案1】:

    属性之所以有效,是因为 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 情况下,有一个不同的元类,它是类型的子类(所以说这个类“不是新样式”是不正确的!),因此事情确实可以正常工作。

    【讨论】:

      【解决方案2】:

      根据我的经验,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 版本。

      【讨论】:

        【解决方案3】:

        至少在 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'>)
        

        【讨论】:

        • 奇怪,可能我们用来检查代码的工具理解错了……
        • 根据 PyQt 文档“在 v4.5 之前的 PyQt 版本中,对使用 super 和 PyQt 类有限制。这些限制不再适用于 v4.5 及更高版本。”如果您使用的是 4.5 之前的版本,也许这就是问题所在?不然我就亏大了! (来源:riverbankcomputing.co.uk/static/Docs/PyQt4/…
        • 我对我的进行了相同的测试,它告诉我同样的事情,我将继续假设我们正在使用的工具只是混淆了。谢谢
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多