Python çoklu dönüş değerini yoksay


274

Bir tuple içinde birden çok değer döndüren bir Python işlevi var diyelim:

def func():
    return 1, 2

Geçici bir değişkene atamak yerine sonuçlardan birini görmezden gelmenin güzel bir yolu var mı? Diyelim ki sadece ilk değerle ilgileniyorsam, bundan daha iyi bir yol var mı:

x, temp = func()

2
Ben de Matlab'ın belirli bir dönüş değişkenini yoksaymak için sözdizimi olarak kullandıkları Yoksayılan İşlev Çıkışlarını benzer fikrinden geldiğini merak ettim~
jxramos

3
Yanlış yanıtı çözüm olarak
AGP

Yanıtlar:


241

Yaygın olarak kullanılan bir kural, yoksaymak istediğiniz grubun öğeleri için değişken bir ad olarak "_" kullanmaktır. Örneğin:

def f():
    return 1, 2, 3

_, _, x = f()

89
-1: Başka birinin koduna gettext işlevselliği eklediğinizde ('_' adlı bir işlevi tanımlayan) bu "kural" berbat olur, bu nedenle yasaklanmalıdır
nosklo

27
İyi bir nokta - gettext'in " " adlı bir işlevi yükleme konusundaki ısrarının iyi bir fikir olup olmadığı tartışmalıdır . Şahsen biraz çirkin buluyorum. Ne olursa olsun, bir değişken değişken olarak " " kullanımı yaygındır.
Brian Clapper

25
-1: _ IPython'da "son çıktı" anlamına gelir. Asla ona bir şey atamam.
Endolit

20
Tamam, ben "Ben" fark etmedim - referans için teşekkürler. IMHO, bir Python uygulaması bunun için kendi sihirli kullanımını tanımladığı için başkalarının bir değişken kullanmamasını bekleyemezsiniz.
Draemon

8
PyDev gibi bazı IDE'ler bu konuda bir uyarı verecektir, çünkü kullanılmayan değişkenleriniz vardır.
teeks99

593

Sen kullanabilirsiniz x = func()[0], ilk değer döndürmek için x = func()[1]böylece ikinci dönmek ve.

Bir kerede birden fazla değer almak istiyorsanız, gibi bir şey kullanın x, y = func()[2:4].


92
Bu kabul edilen cevap olmalı. Ayrıca, func()[2:4]yalnızca döndürme değerlerinden bazılarını istemeniz gibi şeyleri de kullanabilirsiniz .
endolit

11
İşlevi birden çok kez çağırmaz: >>> def test (): ... "burada" yazdır ... ... 1,2,3 ... >>> a, b = test () [: 2 ] here [edit: kodun gelmediği için üzgünüm, yorumlarda yalnızca bir satır alırsınız. Tanıdık olmayanlar için >>> ve ... python kabuğunda yeni bir hattın başlangıcıdır]
teeks99

32
@TylerLong: Bence _, _, _, _, _, _, _, _, _, _, _, _, _, a, _, _, _, _, _, _, _, _, _, _, _, b, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, c, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, d, _, _, _, _, _, _, _, _, e, _ = func()işlevi birden çok kez çağırmaktan daha az net, ama bu sadece benim görüşüm. Eğer fonksiyonunuz bu kadar çok öğeyi döndürürse, numpy kullanmak tercih edilebilir:a, b, c, d, e = func()[[13, 25, 58, 89, 98]]
endolith

24
@ endolith Bence bu daha iyi ve numpy gerekmez ve func () birden çok kez çağırmak gerekmez: result = func() a = result[13] b = result[25]...
Tyler Long

3
Aralarında bir veya birkaç değeri yok saymak istediğinizde bu stil hoş değil, ör.x, __, y = func()
ndemou

96

Python 3 kullanıyorsanız, paketin açılmasında bir liste olması için bir değişkenin önündeki yıldızı (ödevin sol tarafında) kullanabilirsiniz.

# 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
Ayrıca a, *_ = f(), sonradan döndürülen değerlerin rasgele sayısını yok saymak için de kullanabilirsiniz a.
THN

21

Birden fazla öğe döndürdüğünüzde, gerçekten bir demet döndürdüğünüzü unutmayın. Böylece böyle şeyler yapabilirsiniz:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2

17

Ortak uygulama, daha _önce belirtildiği gibi , kukla değişken (tek alt çizgi) kullanmaktır .

Bununla birlikte, bu değişken adının diğer kullanımlarıyla çarpışmaları önlemek için ( bu yanıta bakın ) __, ncoghlan'ın işaret ettiği gibi, bir değişken değişken olarak (çift alt çizgi) kullanmak daha iyi bir uygulama olabilir . Örneğin:

x, __ = func()

Aslında fena bir fikir değil. Ancak '_ _' ad alanında bir değişken bildirir. Oysa yukarıdaki gibi atama ifadesinin sol tarafında özellikle kullanılmadığı sürece '_' beyan etmez (örneğin:) a, _, _ = 1,8,9. Bu noktaya kadar, yakalamak istediğinizde normalde bu değeri saklamak için bir değişken kullanacağınız son ifadenin sonucunu saklar. Bu nedenle, '_' önemsiz değerleri yakalamak için önerilen değişken adıdır. '_' değerlerinin üzerine başka bir deyim yürütüldükten hemen sonra yazılır. '_ _' Durumunda, GC onu temizleyene kadar değer orada kalacaktır.
Archit Kapoor

16

Üç basit seçenek.

Açık

x, _ = func()

x, junk = func()

iğrenç

x = func()[0]

Ve bunu bir dekoratörle yapmanın yolları var.

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

func0= val0(func)

5
_Değişkeni gerçekten tercih ederim . Bir değeri görmezden geldiğiniz çok açık
Claudiu

21
Örnekleriniz geriye dönük. x, _ = func()iğrenç ve x = func()[0]açıktır. Değişkene atama ve sonra kullanmayan? İşlev bir demet döndürüyor; bir demet gibi dizine ekleyin.
Mart'ta endolit

6
Python'un bu kalıbı türettiği kalıp eşleme dillerinde, 'bariz' yöntem gerçekten iğrenç ve kanonik değil, açıktır. Her ne kadar, bu dillerde joker karakter desteklenen bir dil özelliğidir, oysa Python'da gerçek bir değişkendir ve bağlanır, bu da biraz tatsızdır.
Joe

4
Python türetildiği listesi işleme diller için ;), liste gibi erişimcileri a[0], a[:](liste kopya), a[::2](her iki eleman) ve a[i:] + a[:i](döndürme bir liste), aynı zamanda, gerçekten de açıktır ve standart bulunmaktadır.
cod3monk3y

7

Muhtemelen en iyi çözüm, anlamsız tuples döndürmek yerine işleri adlandırmaktır. İade edilen ürünlerin sırasının arkasında bir mantık olmadığı sürece.

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

latitude = func()['lat']

Döndürdüğünüz şey hakkında daha fazla bilgi eklemek istiyorsanız namedtuple bile kullanabilirsiniz (bu sadece bir sözlük değildir, bunlar koordinatlardır):

from collections import namedtuple 

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

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

latitude = func().lat

Sözlüğünüzdeki / dizinizdeki nesneler güçlü bir şekilde birbirine bağlıysa, bunun için bir sınıf tanımlamak bile iyi bir fikir olabilir. Bu şekilde, bu tür nesneler arasındaki etkileşimi tanımlayabilir ve onlarla nasıl çalışılacağı konusunda bir API verebilirsiniz. Aşağıdaki doğal bir soru: Python'da ne zaman sınıf kullanmalıyım? .


4

Bu benim için en iyi seçim gibi görünüyor:

val1, val2, ignored1, ignored2 = some_function()

Şifreli veya çirkin değil (func () [index] yöntemi gibi) ve amacınızı açıkça belirtiyor.


4

Bu soruya doğrudan bir cevap değildir. Bunun yerine şu soruya cevap verir: "Olası birçok seçenek arasından belirli bir işlev çıktısını nasıl seçerim?".

İşlevi yazabiliyorsanız (yani, değiştiremeyeceğiniz bir kitaplıkta değilse), işlevden ne istediğinizi gösteren bir girdi bağımsız değişkeni ekleyin. Varsayılan değere sahip adlandırılmış bir bağımsız değişken yapın, böylece "ortak durumda" belirtmeniz bile gerekmez.

    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 )

Bu yöntem, istenen çıktıya ilişkin "gelişmiş uyarı" işlevini verir. Sonuç olarak, gereksiz işlemeyi atlayabilir ve yalnızca istediğiniz çıktıyı elde etmek için gerekli işi yapabilir. Ayrıca Python dinamik yazım yaptığı için dönüş türü değişebilir. Örneğin nasıl bir skaler, bir liste veya bir demet döndürdüğüne dikkat edin ... ne istersen!


2

Bu her zaman kullandığınız ancak her zaman ikinci argümanı attığınız bir işlevse, ikinci dönüş değeri kullanmadan işlev için bir diğer ad oluşturmanın daha az dağınık olduğunu iddia ederim lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

2

Bir işlevden çok sayıda çıktınız varsa ve bunu birden çok kez çağırmak istemiyorsanız, sonuçları seçmenin en net yolunun şöyle olacağını düşünüyorum:

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

Minimum çalışma örneği olarak, işlevin yalnızca bir kez çağrıldığını da gösterir:

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

Ve değerler beklendiği gibi:

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

Kolaylık sağlamak için Python listesi dizinleri de kullanılabilir:

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

İade: a = 3 ve b = 12

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.