首页
学习
活动
专区
圈层
工具
发布

优化`‘
EN

Stack Overflow用户
提问于 2011-12-28 11:19:10
回答 4查看 293关注 0票数 2

我使用这些构造来测试是否按下了所需的键:

代码语言:javascript
复制
def eventFilter(self, tableView, event):
    if event.type() == QtCore.QEvent.KeyPress:
        key = event.key()
        if event.modifiers() in (QtCore.Qt.NoModifier, QtCore.Qt.KeypadModifier):
            if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
                self.menu.editItem.trigger()
                return True

我知道“过早优化是万恶之源”,但我认为eventFilter经常被调用来考虑它的优化。

我所关切的是:

  1. if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return)对每次运行进行双重查找: 1.在QtCore模块中查找Qt属性;2.在Qt module.
  2. if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return)中查找Key_Enter属性--这将在每次运行时构造元组。元组中的搜索是连续的--更好地使用frozenset

你是如何处理这些案件的?不在乎吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-12-28 13:08:51

你的代码:

代码语言:javascript
复制
def eventFilter(self, tableView, event): 
    if event.type() == QtCore.QEvent.KeyPress: 
        key = event.key() 
        if event.modifiers() in (QtCore.Qt.NoModifier, QtCore.Qt.KeypadModifier): 
            if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): 
                self.menu.editItem.trigger() 
                return True

正如我在@interjay的评论中提到的那样,对于任何类型的UI事件,可能会有大量调用这个函数,如果您有许多这样的过滤器,它们可能会导致一个缓慢的UI。如果您希望至少在第一个If测试的范围内对其进行优化,那么将QtCore.QEvent.KeyPress的本地定义移到默认的参数值中:

代码语言:javascript
复制
def eventFilter(self, tableView, event,
    FILTER_EVENT_TYPE=QtCore.QEvent.KeyPress
    ): 
    if event.type() == FILTER_EVENT_TYPE: 
        if event.modifiers() in (QtCore.Qt.NoModifier, QtCore.Qt.KeypadModifier): 
            key = event.key() 
            if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): 
                self.menu.editItem.trigger() 
                return True

(我还将对event.key()的函数调用移至event.modifiers()上的测试之后。)

在导入模块时,像这样的默认参数会在函数编译时计算一次,而不是每次调用一次,因此您对QtCore.QEvent.KeyPress的查找将被加速。你当然可以把这件事说到极致:

代码语言:javascript
复制
def eventFilter(self, tableView, event,
    FILTER_EVENT_TYPE=QtCore.QEvent.KeyPress
    FILTER_MODIFIERS=(QtCore.Qt.NoModifier, QtCore.Qt.KeypadModifier),
    FILTER_KEYS=(QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return)
    ): 
    if (event.type() == FILTER_EVENT_TYPE and
        event.modifiers() in FILTER_MODIFIERS and 
        event.key() in FILTER_KEYS): 
            self.menu.editItem.trigger() 
            return True

现在,您不仅优化了模块-对象-属性查找,还优化了元组结构,正如@AndrewDalke提到的那样,我对in的测试表明,对于元组的测试比设置大约3或4个元素要快。当条件的任何部分发生故障时,单个条件仍然会短路,因此如果类型不是按键,则不会得到对event.modifiers或event.key的调用。

编辑:我喜欢@ekhumoro对键和修饰符的耦合测试,下面是将其合并到我的代码中的方式:

代码语言:javascript
复制
def eventFilter(self, tableView, event,
    FILTER_EVENT_TYPE=QtCore.QEvent.KeyPress
    FILTER_KEY_MODIFIERS=((QtCore.Qt.Key_Return, QtCore.Qt.NoModifier),
                          (QtCore.Qt.Key_Enter, QtCore.Qt.KeypadModifier),
                          )
    ): 
    if (event.type() == FILTER_EVENT_TYPE and
        (event.key(), event.modifiers()) in FILTER_KEY_MODIFIERS): 
            self.menu.editItem.trigger() 
            return True
票数 3
EN

Stack Overflow用户

发布于 2011-12-28 11:30:47

我同意关于这件事不重要的意见。

但是,如果您想在这里节省时间,那么在Python中删除重复查找成本的标准方法是将对象缓存在局部变量命名空间中:

代码语言:javascript
复制
NoModifier = QtCore.Qt.NoModifier
KeypadModifier = QtCore.Qt.KeypadModifier
if event.modifiers() in (NoModifier, KeypadModifier):
    ...

Python将在局部变量名称空间、模块命名空间中查找变量,最后在全局命名空间中查找变量--因此,您可以通过将内容放入局部变量命名空间来获得一些信息。

但是,这在您的情况下是没有意义的:每个函数调用都会执行一次查找。如果您有一个循环,可以执行许多相同属性的许多查询,那么上面的优化策略就适用了:

代码语言:javascript
复制
for event in huge_pile_of_accumulated_events:
    if event.modifiers() in (NoModifier, KeypadModifier):
        ...

在这里,您可能会保存一些东西--记得先分析一下您的代码,以实际证明这一点是重要的!对于每个键盘事件运行一次的处理程序,查找时间并不重要。

票数 2
EN

Stack Overflow用户

发布于 2011-12-28 20:02:00

虽然多属性查找确实要慢一些,因为我们指的是每次查找不到百万分之一秒,但这种差异将被其他更大的因素所淹没(例如简单调用方法的成本)。因此,这将更多地是一种毫无意义的优化,而不是过早的优化。

但是,如果您真的很关心它,那么只需更改导入语句就可以避免许多查找。

因此,与其做:

代码语言:javascript
复制
from PyQt4 import QtCore

你可以:

代码语言:javascript
复制
from PyQt4.QtCore import QEvent

并避免对模块中的每个QEvent引用进行额外的属性查找(当然,对于以这种方式导入的任何其他类也是如此)。

就我个人而言,我也会避免所有的in测试,而是单独测试每一种可能性。这节省了每次运行测试时创建元组的成本,同时也利用了短路评估的优势。

因此,我将您的示例代码重写为:

代码语言:javascript
复制
from PyQt4.QtCore import Qt, QEvent

def eventFilter(self, tableView, event):
    if event.type() == QEvent.KeyPress:
        key = event.key()
        modifiers = event.modifiers()
        if ((modifiers == Qt.NoModifier and key == Qt.Key_Return) or 
            (modifiers == Qt.KeypadModifier and key == Qt.Key_Enter)):
            self.menu.editItem.trigger()
            return True
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8655224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档