Передача функций, которые имеют несколько возвращаемых значений в качестве аргументов в Python - PullRequest
15 голосов
/ 27 марта 2009

Итак, функции Python могут возвращать несколько значений. Меня поразило, что было бы удобно (хотя и немного менее читабельно), если бы было возможно следующее.

a = [[1,2],[3,4]]

def cord():
    return 1, 1

def printa(y,x):
    print a[y][x]

printa(cord())

... но это не так. Я знаю, что вы можете сделать то же самое, сбросив оба возвращаемых значения во временные переменные, но это не выглядит элегантно. Я мог бы также переписать последнюю строку как «printa (cord () [0], cord () [1])», но это выполнит шнур () дважды.

Есть ли элегантный, эффективный способ сделать это? Или мне просто посмотреть цитату о преждевременной оптимизации и забыть об этом?

Ответы [ 3 ]

23 голосов
/ 27 марта 2009
printa(*cord())

Здесь * является оператором расширения аргумента ... ну, я забыл, как это технически называется, но в этом контексте он берет список или кортеж и раскрывает его, так что функция видит каждый элемент списка / кортежа как отдельный аргумент.

Это, в сущности, обратное *, которое вы можете использовать для захвата всех аргументов, не связанных с ключевыми словами, в определении функции:

def fn(*args):
    # args is now a tuple of the non-keyworded arguments
    print args

fn(1, 2, 3, 4, 5)

отпечатков (1, 2, 3, 4, 5)

fn(*[1, 2, 3, 4, 5])

делает то же самое.

6 голосов
/ 27 марта 2009

Попробуйте это:

>>> def cord():
...     return (1, 1)
...
>>> def printa(y, x):
...     print a[y][x]
...
>>> a=[[1,2],[3,4]]
>>> printa(*cord())
4

Звезда в основном говорит: «используйте элементы этой коллекции в качестве позиционных аргументов». Вы можете сделать то же самое с помощью dict для аргументов ключевых слов, используя две звезды:

>>> a = {'a' : 2, 'b' : 3}
>>> def foo(a, b):
...    print a, b
...
>>> foo(**a)
2 3
4 голосов
/ 28 марта 2009

На самом деле, Python на самом деле не возвращает несколько значений, он возвращает одно значение, которое может быть несколькими значениями, упакованными в кортеж. Это означает, что вам нужно «распаковать» возвращенное значение, чтобы иметь кратные значения. Заявление типа

x,y = cord()

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

printa(cord())

нет, поэтому вам нужно использовать звездочку. Возможно, хорошим термином для этого может быть «неявная распаковка кортежей» или «распаковка кортежей без присваивания».

...