【发布时间】:2014-02-07 07:08:49
【问题描述】:
我有一个嵌套函数,在pyglet 中用作回调:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
return stop_on_key
pyglet.window.set_handler('on_key_press', get_stop_function('ENTER'))
但是后来当我需要再次引用嵌套函数时遇到了问题:
pyglet.window.remove_handler('on_key_press', get_stop_function('ENTER'))
由于 python 处理函数的方式,这不起作用:
my_stop_function = get_stop_function('ENTER')
my_stop_function is get_stop_function('ENTER') # False
my_stop_function == get_stop_function('ENTER') # False
感谢两位 similar questions 我了解发生了什么,但我不确定针对我的情况有什么解决方法。我正在查看pyglet source code,看起来 pyglet 使用相等来查找要删除的处理程序。
所以我的最后一个问题是:如何覆盖内部函数的 __eq__ 方法(或其他一些笨蛋),以便相同的嵌套函数相等?
(另一种解决方法是自己存储对函数的引用,但这是重复 pyglet 的工作,会因许多回调而变得混乱,而且无论如何我对这个问题很好奇!)
编辑:实际上,在我上面链接的问题中,解释了方法具有值相等但不具有引用相等。使用嵌套函数,您甚至无法获得值相等,而这正是我所需要的。
Edit2:我可能会接受 Bi Rico 的回答,但有谁知道为什么以下内容不起作用:
def get_stop_function(stop_key):
def stop_on_key(symbol, _):
if symbol == getattr(pyglet.window.key, stop_key):
pyglet.app.exit()
stop_on_key.__name__ = '__stop_on_' + stop_key + '__'
stop_on_key.__eq__ = lambda x: x.__name__ == '__stop_on_' + stop_key + '__'
return stop_on_key
get_stop_function('ENTER') == get_stop_function('ENTER') # False
get_stop_function('ENTER').__eq__(get_stop_function('ENTER')) # True
【问题讨论】:
-
“相同的函数”是指相同的代码(如,均由
get_stop_function创建)、相同的代码,还是具有相同字节码字符串的不同代码?相同或相等的闭合?等等…… -
你实际上可以覆盖内部函数的
__eq__。在 Python 3.x 中,function是可变的。问题是它不会有任何好处。 Python 3.x 指定允许__eq__查找忽略实例的方法并直接进入类,并且至少 CPython 3.0-3.4 和 PyPy3 2.1(它们是唯一存在的 3.x 实现)正是这样做的。 -
另外,对于您的编辑:我很确定如果函数相等且绑定对象相等,则方法相等,这意味着方法实际上与嵌套函数具有相同的问题 - 函数仍然需要比较相等。只是通常您不会自己构建绑定方法,它们是由类的描述符创建的,在这种情况下,它们的功能将始终相同。 (我觉得我解释得不是很好……)
-
感谢@abarnert,内容丰富。
标签: python python-3.x nested pyglet