python中的Lambda函数比较

sas*_*hab 3 python lambda python-internals

在python中,您无法直接比较lambda表达式创建的函数:

>>> (lambda x: x+2) == (lambda x: x+2)
False
Run Code Online (Sandbox Code Playgroud)

我做了一个例程来散列反汇编.

import sys
import dis
import hashlib
import contextlib


def get_lambda_hash(l, hasher=lambda x: hashlib.sha256(x).hexdigest()):
    @contextlib.contextmanager
    def capture():
        from cStringIO import StringIO
        oldout, olderr = sys.stdout, sys.stderr
        try:
            out=[StringIO(), StringIO()]
            sys.stdout, sys.stderr = out
            yield out
        finally:
            sys.stdout, sys.stderr = oldout, olderr
            out[0] = out[0].getvalue()
            out[1] = out[1].getvalue()

    with capture() as out:
        dis.dis(l)

    return hasher(out[0])
Run Code Online (Sandbox Code Playgroud)

用法是:

>>>> get_lambda_hash(lambda x: x+2) == get_lambda_hash(lambda x: x+1)
False

>>>> get_lambda_hash(lambda x: x+2) == get_lambda_hash(lambda x: x+2)
True
Run Code Online (Sandbox Code Playgroud)

这个问题还有更优雅的解决方案吗?

Ign*_*ams 6

如果你坚持执行这种疯狂的疯狂,请比较每个字节码和常量.

>>> import operator
>>> coco = operator.attrgetter('co_code', 'co_consts')
>>> coco((lambda x: x+2).__code__) == coco((lambda x: x+2).__code__)
True
>>> coco((lambda x: x+2).__code__) == coco((lambda x: x+1).__code__)
False
>>> def foo(y):
...   return y + 2
... 
>>> coco((lambda x: x+2).__code__) == coco(foo.__code__)
True
Run Code Online (Sandbox Code Playgroud)

  • 这可能不够好 - 例如对于 `def f(x): return lambda y: x+y` 它会认为 `f(1)` 和 `f(2)` 是同一个函数。 (2认同)