Rozwijanie krotek na argumenty

411

Czy istnieje sposób na rozszerzenie krotki Python w funkcję - jako rzeczywiste parametry?

Na przykład tutaj expand()działa magia:

some_tuple = (1, "foo", "bar")

def myfun(number, str1, str2):
    return (number * 2, str1 + str2, str2 + str1)

myfun(expand(some_tuple)) # (2, "foobar", "barfoo")

Wiem, że można to zdefiniować myfunjako myfun((a, b, c)), ale oczywiście może istnieć starszy kod. Dzięki

AkiRoss
źródło

Odpowiedzi:

733

myfun(*some_tuple)robi dokładnie to, o co prosisz. *Operator prosto rozpakowuje krotkę (lub dowolny iterowalny), i przekazuje je jako pozycyjnych argumentów funkcji. Przeczytaj więcej o argumentach rozpakowywania .

Alex Martelli
źródło
8
Operator * po prostu rozpakowuje krotkę i przekazuje je jako argumenty pozycyjne do funkcji. Zobacz więcej tutaj: docs.python.org/3/tutorial/…
john_mc
4
Zauważ, że ta sama składnia może być używana zarówno dla list, jak i krotek.
brendon-ai
Przekonałem się, że możesz zrobić to samo z listami (w rzeczywistości dowolnymi iterowalnymi, w tym ciągami), nie będąc pewnym, jak ich zmienność wpływa na rzeczy. Byłoby to interesujące.
wcyn
52

Zauważ, że możesz także rozwinąć część listy argumentów:

myfun(1, *("foo", "bar"))
Valentas
źródło
13
Wygląda na to, że możesz to zrobić tylko wtedy, gdy krotka jest rozwinięta po normalnie podanych argumentach - tłumacz nie lubi, gdy to robię:some_func(*tuple_of_stuff, another_argument)
Tom Galvin
6
@Quackmatic Posiadanie rozszerzonej krotki w dowolnym miejscu wydaje się działać dobrze w Pythonie 3.5.1
River
1
@Quackmatic oddelegowanie @River, działa to dobrze w Pythonie 3.5.4: def func(a,b,c,d): print(a,b,c,d)zargs = ('fee', 'fi', 'fo'); func(*args, 'fum')
R. Navega
15

Spójrz na samouczek Python w sekcjach 4.7.3 i 4.7.4. Mówi o przekazywaniu krotek jako argumentów.

Zastanowiłbym się również nad użyciem nazwanych parametrów (i przekazaniem słownika) zamiast krotki i przekazaniem sekwencji. Uważam, że użycie argumentów pozycyjnych jest złą praktyką, gdy pozycje nie są intuicyjne lub istnieje wiele parametrów.

Uri
źródło
8

Jest to metoda programowania funkcjonalnego. Podnosi funkcję rozszerzenia krotek z cukru składniowego:

apply_tuple = lambda f, t: f(*t)

Przykładowe użycie:

from toolz import * 
from operator import add, eq

apply_tuple = curry(apply_tuple)

thread_last(
    [(1,2), (3,4)],
    (map, apply_tuple(add)),
    list,
    (eq, [3, 7])
)
# Prints 'True'

redefiniton curryapply_tuple pozwala zaoszczędzić wiele partialpołączeń na dłuższą metę.

Dominykas Mostauskis
źródło
5
To nie jest pomocne dla początkującego. Korzysta z modułów innych firm i robi inne mylące rzeczy ...
gberger
gberger, lambda f, t: f(*t)nie używa zewnętrznych modułów i jestem początkującym w Pythonie, co jest dla mnie pomocne. Jest to podejście czysto funkcjonalne. Jeśli nie używasz tego stylu, ta odpowiedź nie jest dla ciebie.
Dominykas Mostauskis
1
Toolz to firma zewnętrzna, to miałem na myśli
gberger
5
Nie każda odpowiedź musi być dla początkującego
Jordan
1
W podanym przykładzie można użyć starmap docs.python.org/3.7/library/itertools.html#itertools.starmap
Bo.