2012-08-06 18 views
11

W Pythonie, przypuśćmy, że mam funkcję f, którą chcę przekazać z pewnymi drugorzędnymi argumentami (zakładam dla prostoty, że to tylko pierwszy argument, który pozostaje zmienny).Różnice między functools.partial i podobną lambda?

Jakie są różnice między robieniem tych dwóch sposobów (jeśli istnieją)?

# 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) 

W doc page for partial, na przykład, nie jest to cytat:

partial obiekty zdefiniowane w klasach zachowywać się jak metody statyczne i nie przekształci związanych metod podczas przykład atrybut przeglądowej.

Czy metoda lambda cierpi z tego powodu, aby zastosować metodę klasy z argumentów podanych do klasy (w konstruktorze lub później w funkcji)?

+1

Myślę, że moje pytanie jest zupełnie inne niż powiązane, jednak górna odpowiedź na to pytanie jest tak dokładna, że ​​odpowiada (przez przypadek) na wiele z tego, czego szukałem. Nie będę narzekał, jeśli zostanie zamknięty jako duplikat. – ely

+0

Zgadzam się, że to nie jest duplikat, ponownie otworzyłem pytanie. Jeśli chodzi o inne odniesienia, pokrewnym pytaniem jest [tutaj] (http://stackoverflow.com/questions/220658/what-is-the-difference-between--closure- and -a-ambda). – wim

Odpowiedz

9
  1. Funkcja lambda ma ten sam typ co funkcja standardowa, więc zachowuje się jak metoda instancji.

  2. partial obiekt w swoim przykładzie można nazwać tak:

    g1(x, y, z) 
    

    prowadzi do tego wezwania (nie ważne składni Pythona, ale masz pomysł):

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

    lambda akceptuje tylko jeden argument i używa innej kolejności argumentów. (Oczywiście oba te różnice można przezwyciężyć - Ja tylko odpowiadając jakie są różnice między tymi dwoma wersjami dałeś są).

  3. wykonanie przedmiotu partial jest nieco szybciej niż wykonanie równoważnych lambda.

+0

Czy profilowałeś obiekt 'częściowy' w porównaniu do' lambda'? – orlp

+2

@ noccracker: Tak, nie teraz, ale kilka razy w przeszłości. Obiekt 'partial' nie tworzy obiektu kodu Python, więc zapisuje pełną ramkę stosu Pythona. –

+0

@Sven Marnach: a czym dokładnie jest szybciej, kod kreacji, kod wywołujący lub jedno i drugie? – orlp

0

Wierzę, że rzecz klasy ma zastosowanie tylko do funkcji przypisanych podczas definiowania klasy. Funkcje przypisane później nie są traktowane specjalnie.

Poza tym osobiście faworyzowałbym lambdas, ponieważ są one bardziej powszechne i dlatego ułatwiają zrozumienie kodu.

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

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

'Osobiście faworyzuję lambdas, ponieważ są one bardziej powszechne i dlatego ułatwiają zrozumienie kodu." Nigdy wcześniej nie słyszałem żadnego z tych stwierdzeń. – phant0m

+0

@ phant0m Większość stwierdzeń, które słyszałem o Python lambdas, zawierało w nich słowo "broken". ;-) –

+0

@Chris functools.partial jest czystszy, ale myślę, że lambdy są łatwiejsze do zrozumienia, o ile nie masz problemów z zakresu. Przede wszystkim, lambdas oznacza, że ​​nie musisz pamiętać dokładnej kolejności argumentów, jaką ma functools.partial. – Antimony

0

Tak, lambda będzie "cierpieć" z tego powodu. partial nie ma tego problemu, ponieważ jest obiektem z przeciążonym operatorem połączenia, a nie rzeczywistą funkcją.

Ale używanie lambda w definicji klasy to po prostu niewłaściwe użycie.

0

partials nie są tylko o 20% szybciej niż równoważne lambdas jak już zostało powiedziane, ale zachować bezpośredni wg one działają tak dotyczą. Podczas gdy w lambdach funkcja ta jest "pochowana" w ciele funkcji.

=> Jeśli potrzebujesz tylko rozwiązać problem odroczenia oceny jednej funkcji, aż wszystkie znane są, użyj częściowych. Będziesz miał znacznie lepsze metody introspekcji w porównaniu do zakotwiczenia połączeń w anonimowe funkcje, np. Lambda.