我使用这些构造来测试是否按下了所需的键:
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经常被调用来考虑它的优化。
我所关切的是:
if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return)对每次运行进行双重查找: 1.在QtCore模块中查找Qt属性;2.在Qt module.if key in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return)中查找Key_Enter属性--这将在每次运行时构造元组。元组中的搜索是连续的--更好地使用frozenset。
你是如何处理这些案件的?不在乎吗?
发布于 2011-12-28 13:08:51
你的代码:
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的本地定义移到默认的参数值中:
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的查找将被加速。你当然可以把这件事说到极致:
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对键和修饰符的耦合测试,下面是将其合并到我的代码中的方式:
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发布于 2011-12-28 11:30:47
我同意关于这件事不重要的意见。
但是,如果您想在这里节省时间,那么在Python中删除重复查找成本的标准方法是将对象缓存在局部变量命名空间中:
NoModifier = QtCore.Qt.NoModifier
KeypadModifier = QtCore.Qt.KeypadModifier
if event.modifiers() in (NoModifier, KeypadModifier):
...Python将在局部变量名称空间、模块命名空间中查找变量,最后在全局命名空间中查找变量--因此,您可以通过将内容放入局部变量命名空间来获得一些信息。
但是,这在您的情况下是没有意义的:每个函数调用都会执行一次查找。如果您有一个循环,可以执行许多相同属性的许多查询,那么上面的优化策略就适用了:
for event in huge_pile_of_accumulated_events:
if event.modifiers() in (NoModifier, KeypadModifier):
...在这里,您可能会保存一些东西--记得先分析一下您的代码,以实际证明这一点是重要的!对于每个键盘事件运行一次的处理程序,查找时间并不重要。
发布于 2011-12-28 20:02:00
虽然多属性查找确实要慢一些,因为我们指的是每次查找不到百万分之一秒,但这种差异将被其他更大的因素所淹没(例如简单调用方法的成本)。因此,这将更多地是一种毫无意义的优化,而不是过早的优化。
但是,如果您真的很关心它,那么只需更改导入语句就可以避免许多查找。
因此,与其做:
from PyQt4 import QtCore你可以:
from PyQt4.QtCore import QEvent并避免对模块中的每个QEvent引用进行额外的属性查找(当然,对于以这种方式导入的任何其他类也是如此)。
就我个人而言,我也会避免所有的in测试,而是单独测试每一种可能性。这节省了每次运行测试时创建元组的成本,同时也利用了短路评估的优势。
因此,我将您的示例代码重写为:
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 Truehttps://stackoverflow.com/questions/8655224
复制相似问题