Игнорировать многократное возвращаемое значение Python

275

Скажем, у меня есть функция Python, которая возвращает несколько значений в кортеже:

def func():
    return 1, 2

Есть ли хороший способ игнорировать один из результатов, а не просто присваивать временную переменную? Скажите, если бы меня интересовало только первое значение, есть ли лучший способ, чем этот:

x, temp = func()
Мат
источник
2
Мне также стало любопытно, что это связано с аналогичным понятием Matlab о Ignore Function Outputs, где они используют ~в качестве синтаксиса игнорирование определенной возвращаемой переменной
jxramos
3
Вы выбрали неверный ответ в качестве решения
AGP

Ответы:

243

Одно общее соглашение заключается в использовании «_» в качестве имени переменной для элементов кортежа, которые вы хотите игнорировать. Например:

def f():
    return 1, 2, 3

_, _, x = f()
Брайан Клаппер
источник
89
-1: это «соглашение» сосет, когда вы добавляете функциональность gettext в чужой код (который определяет функцию с именем «_»), поэтому его следует запретить
nosklo
27
Хорошая мысль - хотя это спорно ли настойчивое GetText по установке функции под названием « » является хорошей идеей. Лично я нахожу это немного некрасивым. Несмотря на это, использование " " в качестве одноразовой переменной широко распространено.
Брайан Клаппер
25
-1: _ означает «последний вывод» в IPython. Я бы никогда не назначил что-то на это.
эндолит
20
Хорошо, я не заметил "я" - спасибо за ссылку. ИМХО, вы не можете ожидать, что другие не будут использовать переменную только потому, что одно приложение Python определяет свое собственное магическое использование для нее.
Draemon
8
некоторые IDE, такие как PyDev, будут предупреждать вас об этом, потому что у вас есть неиспользуемые переменные.
teeks99
597

Вы можете использовать, x = func()[0]чтобы вернуть первое значение, x = func()[1]вернуть второе и так далее.

Если вы хотите получить несколько значений одновременно, используйте что-то вроде x, y = func()[2:4].

Люк Вудворд
источник
92
Это должен быть принятый ответ. Вы также можете использовать такие вещи, как, func()[2:4]если вы хотите только некоторые из возвращаемых значений.
эндолит
11
Он не вызывает функцию несколько раз: >>> def test (): ... print "here" ... return 1,2,3 ... >>> a, b = test () [: 2 ] здесь [править: извините, что код не прошел, по-видимому, вы получаете только одну строку в комментариях. Для тех, кто не знаком >>> и ... это начало новой строки в оболочке Python]
teeks99
32
@TylerLong: Я думаю, что _, _, _, _, _, _, _, _, _, _, _, _, _, a, _, _, _, _, _, _, _, _, _, _, _, b, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, c, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, d, _, _, _, _, _, _, _, _, e, _ = func()это менее понятно, чем многократный вызов функции, но это только мое мнение. Если ваша функция возвращает столько элементов, я думаю, что было бы предпочтительнее использовать numpy:a, b, c, d, e = func()[[13, 25, 58, 89, 98]]
endolith
24
@endolith Я думаю, что это лучше и не нуждается в numpy и не нужно вызывать func () несколько раз: result = func() a = result[13] b = result[25]...
Tyler Long
3
Этот стиль не подходит, если вы хотите игнорировать одно или несколько значений между ними, напримерx, __, y = func()
ndemou
96

Если вы используете Python 3, вы можете использовать звездочку перед переменной (слева от присваивания), чтобы она была списком при распаковке.

# Example 1: a is 1 and b is [2, 3]

a, *b = [1, 2, 3]

# Example 2: a is 1, b is [2, 3], and c is 4

a, *b, c = [1, 2, 3, 4]

# Example 3: b is [1, 2] and c is 3

*b, c = [1, 2, 3]       

# Example 4: a is 1 and b is []

a, *b = [1]
Джо
источник
2
Вы также можете использовать, a, *_ = f()чтобы игнорировать произвольное количество возвращаемых значений после a.
THN
21

Помните, что когда вы возвращаете более одного предмета, вы действительно возвращаете кортеж. Так что вы можете делать такие вещи:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2
Эван Фосмарк
источник
17

Обычная практика - использовать фиктивную переменную _(одиночное подчеркивание), как многие указывали здесь ранее.

Однако, чтобы избежать коллизий с другими использованиями этого имени переменной (см. Этот ответ), было бы лучше использовать __вместо этого (двойное подчеркивание) в качестве одноразовой переменной, как указано ncoghlan . Например:

x, __ = func()
апатичный
источник
Неплохая идея. Но тогда '_ _' объявит переменную в пространстве имен. Принимая во внимание, что «_» не объявляет, если не используется специально в левой части оператора присваивания, как указано выше (например:) a, _, _ = 1,8,9. До этого момента он хранит результат последнего выполненного оператора, который, если вы хотите перехватить, обычно использует переменную для хранения этого значения. И именно поэтому «_» - это рекомендуемое имя переменной для перехвата ненужных значений. '_' значения перезаписываются вскоре после выполнения другого оператора. В случае '_ _' значение будет оставаться там до тех пор, пока GC не очистит его.
Archit Kapoor
16

Три простых варианта

очевидный

x, _ = func()

x, junk = func()

отвратительный

x = func()[0]

И есть способы сделать это с декоратором.

def val0( aFunc ):
    def pick0( *args, **kw ):
        return aFunc(*args,**kw)[0]
    return pick0

func0= val0(func)
С. Лотт
источник
5
Я действительно предпочитаю _переменную. Совершенно очевидно, что вы игнорируете значение
Claudiu
21
Ваши примеры задом наперед. x, _ = func()отвратительно и x = func()[0]очевидно. Присваивание переменной, а затем ее не использование? Функция возвращает кортеж; индексировать это как кортеж.
эндолит
6
В языках соответствия шаблонов, из которых Python получил этот шаблон, «очевидный» метод действительно очевиден, а не отвратителен и каноничен. Хотя в таких языках подстановочный знак является поддерживаемой языковой функцией, тогда как в Python это реальная переменная, которая становится связанной, что немного неприятно.
Джо
4
Для списка обработки языков, из которых получают Python ;), список таких как методы доступа a[0], a[:](список копия), a[::2](каждые два элемента), и a[i:] + a[:i](вращать список), действительно, также очевидно и каноническим.
cod3monk3y
7

Лучшее решение, вероятно, состоит в том, чтобы называть вещи, а не возвращать бессмысленные кортежи. Если за порядком возвращенных товаров нет логики.

def func():
    return {'lat': 1, 'lng': 2}

latitude = func()['lat']

Вы даже можете использовать namedtuple, если хотите добавить дополнительную информацию о том, что вы возвращаете (это не просто словарь, это координаты):

from collections import namedtuple 

Coordinates = namedtuple('Coordinates', ['lat', 'lng'])

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

Если объекты в вашем словаре / кортеже сильно связаны друг с другом, то было бы неплохо даже определить класс для него. Таким образом, вы также сможете определить взаимодействие между объектами этого типа и дать API о том, как с ними работать. Естественный вопрос: когда мне следует использовать классы в Python? ,

cglacet
источник
4

Это кажется лучшим выбором для меня:

val1, val2, ignored1, ignored2 = some_function()

Он не загадочный и не уродливый (как метод func () [index]), и в нем четко указана ваша цель.

kmelvn
источник
4

Это не прямой ответ на вопрос. Скорее, он отвечает на этот вопрос: «Как выбрать вывод конкретной функции из множества возможных вариантов?».

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

    def fancy_function( arg1, arg2, return_type=1 ):
        ret_val = None
        if( 1 == return_type ):
            ret_val = arg1 + arg2
        elif( 2 == return_type ):
            ret_val = [ arg1, arg2, arg1 * arg2 ]
        else:
            ret_val = ( arg1, arg2, arg1 + arg2, arg1 * arg2 ) 
        return( ret_val )

Этот метод дает функцию «расширенное предупреждение» относительно желаемого выхода. Следовательно, он может пропустить ненужную обработку и выполнять только работу, необходимую для получения желаемого результата. Кроме того, поскольку Python выполняет динамическую типизацию, тип возвращаемого значения может измениться. Обратите внимание, как пример возвращает скаляр, список или кортеж ... что угодно!

1-IJK
источник
2

Если это функция, которую вы используете все время, но всегда отбрасываете второй аргумент, я бы сказал, что создавать псевдоним для функции без использования второго возвращаемого значения не так уж и сложно lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 
Chrigi
источник
2

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

results = fct()
a,b = [results[i] for i in list_of_index]

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

def fct(a):
    b=a*2
    c=a+2
    d=a+b
    e=b*2
    f=a*a
    print("fct called")
    return[a,b,c,d,e,f]

results=fct(3)
> fct called

x,y = [results[i] for i in [1,4]]

И значения, как и ожидалось:

results
> [3,6,5,9,12,9]
x
> 6
y
> 12

Для удобства можно также использовать индексы списка Python:

x,y = [results[i] for i in [0,-2]]

Возвращает: а = 3 и б = 12

jeannej
источник