嵌套函数相等的解决方法

ont*_*ist 5 python nested pyglet python-3.x

我有一个嵌套函数,我用它作为回调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'))
Run Code Online (Sandbox Code Playgroud)

但是当我需要再次引用嵌套函数时,我会遇到问题:

pyglet.window.remove_handler('on_key_press', get_stop_function('ENTER'))
Run Code Online (Sandbox Code Playgroud)

由于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
Run Code Online (Sandbox Code Playgroud)

感谢两个类似的 问题我理解发生了什么,但我不确定我的案例的解决方法是什么.我正在查看pyglet源代码,它看起来像pyglet使用相等来找到要删除的处理程序.

所以我的最后一个问题是:如何覆盖内部函数的__eq__方法(或其他一些dunder),以便相同的嵌套函数相等?

(另一种解决方法是自己存储对函数的引用,但这会复制pyglet的工作,会因许多回调而变得混乱,反正我对这个问题很好奇!)

编辑:实际上,在我上面链接的问题中,它解释了方法具有值相等但不具有引用相等性.使用嵌套函数,您甚至无法获得值相等,这就是我所需要的.

编辑2:我可能接受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
Run Code Online (Sandbox Code Playgroud)

Bi *_*ico 3

您可以为您的停止函数创建一个类并定义您自己的比较方法。

class StopFunction(object):

    def __init__(self, stop_key):
        self.stop_key = stop_key

    def __call__(self, symbol, _):
        if symbol == getattr(pyglet.window.key, self.stop_key):
            pyglet.app.exit()

    def __eq__(self, other):
        try:
            return self.stop_key == other.stop_key
        except AttributeError:
            return False

StopFunciton('ENTER') == StopFunciton('ENTER')
# True
StopFunciton('ENTER') == StopFunciton('FOO')
# False
Run Code Online (Sandbox Code Playgroud)