Если вы действительно хотите знать, будут ли две функции всегда делать то же самое для всех входов, вам придется запускать их как на всех входах (которые будут занимать бесконечное время), так и перехватывать все возможные побочные эффекты (которые фактически невозможно).
Конечно, вы можете придумать несколько эвристик, набросив на них набор различных значений, которые, в свою очередь, могут создавать разные выходы, если функции разные. Но очевидно, что для этого нет универсального решения - иначе все модульные тесты будут генерироваться автоматически, что позволит нам справиться со всей работой, не так ли?
С другой стороны, вы можете просто знать, имеет ли две функции ту же самую реализацию. Для этого ответ Martijn Pieters является очевидной отправной точкой и, возможно, даже конечной точкой (в зависимости от того, заботитесь ли вы о закрытии, глобалах и т. Д.).
Но то, о чем вы просили, отличается от любого из них; вы, очевидно, хотите просмотреть код вручную, чтобы увидеть «как это работает»:
Другим решением может быть некоторый метод, который я могу использовать для функции, чтобы увидеть, что она содержит, и как она работает. Таким образом (lambda x: x) .what(), который вернет способ работы метода, может быть, в словаре или что-то в этом роде.
Эта функция уже существует: dis.dis
. Когда вы запускаете его для функции, он сообщает вам, как работает эта функция. Не в словаре (словаре чего?), А в последовательности строк байт-кода для интерпретатора Python (который является относительно простой стековой машиной с добавлением более высокоуровневого материала сверху, в основном описанным здесь, в документах dis
) ,
Или, проще говоря, вы можете получить исходное сообщение с inspect.getsource
.
Вот что два похожи с примерами:
>>> f1 = lambda x: x
>>> f2 = lambda y: y
>>> def f3(z):
... return z
>>> dis.dis(f1)
1 0 LOAD_FAST 0 (x)
3 RETURN_VALUE
>>> dis.dis(f2)
1 0 LOAD_FAST 0 (y)
3 RETURN_VALUE
>>> dis.dis(f3)
1 0 LOAD_FAST 0 (z)
3 RETURN_VALUE
>>> inspect.getsource(f1)
'f1 = lambda x: x\n'
>>> inspect.getsource(f2)
'f2 = lambda y: y\n'
>>> inspect.getsource(f3)
'def f3(z):\n return z\n'
В первом случае, вы должны знать достаточно о dis
, чтобы понять, что (x)
и т.д., не являются частью байткод, но скорее часть списка локальных имен функции. (Это объясняется так же, как и в документах inspect
, как в документах dis
.) Во-вторых, вам нужно знать достаточно о Python, чтобы понять, что def
и lambda
определяют ту же самую функцию. Итак, в любом случае, нет никакого способа для автоматизировать это (или, действительно, что-нибудь многое, кроме ответа Martijn).
Тесно связанный: [Разработка эвристики для проверки простых анонимных функций Python для эквивалентности] (http://stackoverflow.com/q/9963155), [Clojure test for equal of function expression] (http://stackoverflow.com/q/9393713) –
... хотя ответы на вопрос Python, похоже, предполагают, что невозможно получить байт-код напрямую, и поэтому вам нужно его разобрать, а затем попытаться удалить все лишние вещи, которые дизассемблер добавил из других источников, кроме байт-код, который является глупым, когда на самом деле вполне возможно (и намного проще) просто получить байт-код напрямую ... – abarnert
В случае, если кто-то еще пришел сюда, чтобы узнать, как сравнить две ссылки на одну и ту же функцию: 'f == g' работает для меня – lucidbrot