Ігноруйте кратне повернене значення python


274

Скажіть, у мене є функція Python, яка повертає декілька значень у кортежі:

def func():
    return 1, 2

Чи є приємний спосіб ігнорувати один з результатів, а не просто призначати тимчасову змінну? Скажіть, якщо мене зацікавило лише перше значення, чи є кращий спосіб, ніж цей:

x, temp = func()

2
Мені теж цікаво, що це походить від подібного поняття ~
Матлаба

3
Ви вибрали неправильну відповідь як рішення
AGP

Відповіді:


241

Однією загальною умовою є використання "_" як назви змінної для елементів кортежу, які ви хочете ігнорувати. Наприклад:

def f():
    return 1, 2, 3

_, _, x = f()

89
-1: ця "конвенція" відмовляється, коли ви додаєте функцію gettext до чужого коду (який визначає функцію, що називається "_"), тому її слід заборонити
nosklo

27
Хороший момент - хоча це дискусійне питання про те, чи наполягання gettext на встановленні функції під назвою " " є хорошою ідеєю. Особисто я вважаю це трохи некрасивим. Незалежно від використання " " як перемінної змінної є широко поширеним.
Брайан Клаппер

25
-1: _ означає "останній вихід" в IPython. Я б ніколи щось їй не призначав.
ендоліт

20
Гаразд, я не помітив "Я" - дякую за довідку. IMHO, ви не можете очікувати, що інші не використовуватимуть змінну лише тому, що одна програма Python визначає її власне магічне використання для неї.
Draemon

8
деякі IDE, такі як PyDev, попередить вас про це, оскільки у вас є невикористані змінні.
teeks99

593

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

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


92
Це має бути прийнятою відповіддю. Ви також можете використовувати такі речі, як, func()[2:4]якщо ви хочете лише деякі повернені значення.
ендоліт

11
Він не викликає функцію кілька разів: >>> def test (): ... надрукувати "тут" ... повернути 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 Я вважаю, що це краще і не потребує нуме і йому не потрібно дзвонити func () кілька разів: result = func() a = result[13] b = result[25]...
Тайлер Лонг

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 не очистить його.
Архит Капур

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
Я дуже віддаю перевагу _змінній. Дуже очевидно, що ви ігноруєте значення
Клавдіу

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']

Ви навіть можете використати nametuple, якщо хочете додати додаткову інформацію про те, що повертаєтесь (це не лише словник, це координати):

from collections import namedtuple 

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

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

latitude = func().lat

Якщо об'єкти у вашому словнику / кортежі сильно зв'язані між собою, можливо, було б навіть добре визначити клас для нього. Таким чином ви також зможете визначити взаємодію між об'єктами цього типу та надати API, як працювати з ними. Закономірне питання, що випливає: Коли я повинен використовувати класи на Python? .


4

Це здається мені найкращим вибором:

val1, val2, ignored1, ignored2 = some_function()

Це не нахабно або некрасиво (як метод func () [index]), і чітко визначає ваше призначення.


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 робить динамічне введення тексту, тип повернення може змінюватися. Зауважте, як приклад повертає скаляр, список чи кортеж ... все, що вам подобається!


2

Якщо це функція, яку ви використовуєте весь час, але завжди відкидаєте другий аргумент, я б стверджував, що створити псевдонім для функції без другого поверненого значення менш брудно lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

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]]

Повертає: a = 3 і b = 12

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.