Expandindo tuplas em argumentos

411

Existe uma maneira de expandir uma tupla Python em uma função - como parâmetros reais?

Por exemplo, aqui expand()está a mágica:

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

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

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

Eu sei que alguém poderia definir myfuncomo myfun((a, b, c)), mas é claro que pode haver código legado. obrigado

AkiRoss
fonte

Respostas:

734

myfun(*some_tuple)faz exatamente o que você solicita. O *operador simplesmente descompacta a tupla (ou qualquer iterável) e as passa como argumentos posicionais para a função. Leia mais sobre como descompactar argumentos .

Alex Martelli
fonte
8
O operador * simplesmente descompacta a tupla e os passa como argumentos posicionais para a função. Veja mais aqui: docs.python.org/3/tutorial/…
john_mc
4
Observe que a mesma sintaxe pode ser usada para listas e tuplas.
Brendon-ai
Descobri que você pode fazer o mesmo com listas (de fato, qualquer iterável, incluindo strings), sem ter certeza de como a mutabilidade deles afeta as coisas. Isso seria interessante de se analisar.
Wcyn 26/11
52

Observe que você também pode expandir parte da lista de argumentos:

myfun(1, *("foo", "bar"))
Valentas
fonte
13
Parece que você só pode fazer isso se o tuple expandido é depois que os argumentos normalmente fornecidos - o intérprete não gosta quando eu faço isso:some_func(*tuple_of_stuff, another_argument)
Tom Galvin
6
@Quackmatic Ter a tupla expandida em qualquer local parece funcionar bem no Python 3.5.1
River
1
Destacamento @Quackmatic @River, esta multa funciona em Python 3.5.4: def func(a,b,c,d): print(a,b,c,d)comargs = ('fee', 'fi', 'fo'); func(*args, 'fum')
R. Navega
15

Dê uma olhada na seção 4.7.3 e 4.7.4 do tutorial em Python . Ele fala sobre passar tuplas como argumentos.

Também consideraria usar parâmetros nomeados (e passar um dicionário) em vez de usar uma tupla e passar uma sequência. Acho que o uso de argumentos posicionais é uma má prática quando as posições não são intuitivas ou existem vários parâmetros.

Uri
fonte
8

Este é o método de programação funcional. Ele tira o recurso de expansão da tupla do açúcar de sintaxe:

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

Exemplo de uso:

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'

A redefinição de curryapply_tuple economiza muitas partialchamadas a longo prazo.

Dominykas Mostauskis
fonte
5
Isso não é útil para iniciantes. Ele usa módulos de terceiros e faz outras coisas confuso ...
gberger
gberger, lambda f, t: f(*t)não usa módulos de terceiros e eu sou iniciante em Python e isso é útil para mim. Esta é uma abordagem funcional pura. Se você não usar esse estilo, então esta resposta não é para você.
Dominykas Mostauskis
1
Toolz é de terceiros, é o que eu quis dizer
gberger
5
Nem toda resposta tem que ser para um iniciante
Jordan
1
Para o exemplo que você deu, pode-se usar starmap docs.python.org/3.7/library/itertools.html#itertools.starmap
Bo.