Различия между functools.partial и аналогичной лямбдой?

В Python предположим, что у меня есть функция f, которую я хочу передать с некоторыми вторичными аргументами (предположим для простоты, что это только первый аргумент, который остается переменным).

В чем разница между этими двумя способами (если есть)?

# Assume secondary_args and secondary_kwargs have been defined

import functools

g1 = functools.partial(f, *secondary_args, **secondary_kwargs)
g2 = lambda x: f(x, *secondary_args, **secondary_kwargs)

На странице doc для partial, например, есть эта цитата:

partial объекты, определенные в классах, ведут себя как статические методы и не преобразуются в связанные методы при просмотре атрибутов экземпляра.

Может ли этот лямбда-метод страдать от этого, если используется для создания метода класса из аргументов, предоставленных классу (либо в конструкторе, либо через функцию позже)?

Ответ 1

  • Лямбда-функция имеет тот же тип, что и стандартная функция, поэтому она будет вести себя как метод экземпляра.

  • Объект partial в вашем примере можно вызвать следующим образом:

    g1(x, y, z)
    

    приводящий к этому вызову (недействительный синтаксис Python, но вы получаете идею):

    f(*secondary_args, x, y, z, **secondary_kwargs)
    

    Лямбда принимает только один аргумент и использует другой порядок аргументов. (Конечно, оба эти различия могут быть преодолены - я просто отвечаю на то, что различия между двумя версиями вы дали.)

  • Выполнение объекта partial выполняется немного быстрее, чем выполнение эквивалентного lambda.

Ответ 2

Я считаю, что предмет метода класса применим только к функциям, назначенным во время определения класса. Функции, назначенные позже, не обрабатываются специально.

Кроме этого, я лично одобряю лямбда, поскольку они более распространены и, следовательно, делают код более понятным.

class Foo(object):
    def __init__(self, base):
        self.int = lambda x:int(x, base)

print Foo(4).int('11')

Ответ 3

Да, lambda будет "страдать" от этого. partial не имеет этой проблемы, потому что это объект с перегруженным оператором вызова, а не с реальной функцией.

Но использование лямбда, подобного этому в определении класса, является просто неправильным использованием.

Ответ 4

Частичные части не только на 20% быстрее, чем эквивалентные лямбда, как уже сказано, но они сохраняют прямой рефлекс, к которому они относятся. В то время как в lambdas эта функция "обрывается" внутри тела функции.

= > Если вам нужно решить проблему отсрочки оценки одной функции до тех пор, пока не будут известны все аргументы, используйте частичные. У вас будут лучшие методы интроспекции по сравнению с похоронами вызовов в анонимные функции, т.е. Lambdas.