ละเว้น python หลายค่าที่ส่งคืน


274

ว่าฉันมีฟังก์ชั่น Python ที่ส่งกลับค่าหลายค่าใน tuple:

def func():
    return 1, 2

มีวิธีที่ดีที่จะเพิกเฉยต่อผลลัพธ์อย่างใดอย่างหนึ่งแทนที่จะแค่กำหนดให้กับตัวแปรชั่วคราวหรือไม่? พูดถ้าฉันสนใจเฉพาะค่าแรกมีวิธีที่ดีกว่านี้ไหม:

x, temp = func()

2
ฉันอยากรู้ว่าสิ่งนี้มาจากความคิดที่คล้ายกันของ Matlab ของฟังก์ชันเอาท์พุทฟังก์ชั่นที่พวกเขาใช้~เป็นไวยากรณ์เพื่อละเว้นตัวแปรส่งคืนโดยเฉพาะ
jxramos

3
คุณเลือกคำตอบที่ผิดเป็นวิธีแก้ปัญหา
AGP

คำตอบ:


241

หนึ่งในหลักการทั่วไปคือการใช้ "_" เป็นชื่อตัวแปรสำหรับองค์ประกอบของ tuple ที่คุณต้องการละเว้น ตัวอย่างเช่น

def f():
    return 1, 2, 3

_, _, x = f()

89
-1: นี้ "การประชุม" ครับเมื่อคุณเพิ่มฟังก์ชันการทำงาน gettext รหัสของคนอื่น (ที่กำหนดฟังก์ชั่นที่เรียกว่า '_') ดังนั้นจึงควรจะห้าม
nosklo

27
จุดดี - แม้ว่าจะเป็นที่ถกเถียงกันว่าการเรียกใช้ gettext ในการติดตั้งฟังก์ชันที่เรียกว่า " " เป็นความคิดที่ดีหรือไม่ โดยส่วนตัวฉันคิดว่ามันน่าเกลียดนิดหน่อย การใช้ " " เป็นตัวแปรที่ใช้กับการส่งสัญญาณนั้นแพร่หลายมาก
46416 Brian Clapper

25
-1: _ หมายถึง "เอาต์พุตล่าสุด" ใน IPython ฉันจะไม่มอบหมายอะไรให้
endolith

20
ตกลงฉันไม่ได้สังเกตเห็น "ฉัน" - ขอบคุณสำหรับการอ้างอิง IMHO คุณไม่สามารถคาดหวังให้คนอื่นไม่ใช้ตัวแปรเพียงเพราะแอพ Python หนึ่งแอพกำหนดใช้เวทย์มนตร์ของมันเอง
Draemon

8
IDE บางตัวเช่น PyDev จะให้คำเตือนเกี่ยวกับเรื่องนี้เพราะคุณมีตัวแปรที่ไม่ได้ใช้
teeks99

593

คุณสามารถใช้x = func()[0]เพื่อคืนค่าแรกx = func()[1]เพื่อคืนค่าที่สองและอื่น ๆ

x, y = func()[2:4]หากคุณต้องการที่จะได้รับค่าหลายค่าในเวลาที่ใช้สิ่งที่ต้องการ


92
นี่ควรเป็นคำตอบที่ยอมรับได้ คุณสามารถใช้สิ่งต่าง ๆ เช่นfunc()[2:4]ถ้าคุณต้องการเพียงบางส่วนของค่าตอบแทน
endolith

11
ไม่เรียกใช้ฟังก์ชันหลาย ๆ ครั้ง: >>> def test (): ... พิมพ์ "ที่นี่" ... ส่งคืน 1,2,3 ... >>> a, b = test () [: 2 ] ที่นี่ [แก้ไข: ขออภัยที่โค้ดไม่ผ่านมาโดยปกติคุณจะได้รับความคิดเห็นเพียงบรรทัดเดียว สำหรับผู้ที่ไม่คุ้นเคย >>> และ ... เป็นการเริ่มต้นของบรรทัดใหม่ใน python shell]
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] ...
ไทเลอร์ยาว

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]เห็นได้ชัด การกำหนดให้กับตัวแปรแล้วไม่ได้ใช้มัน? ฟังก์ชันกำลังคืนค่า tuple จัดทำดัชนีเหมือน tuple
endolith

6
ในภาษาที่จับคู่รูปแบบซึ่งไพ ธ อนได้รับรูปแบบนี้วิธีการ 'ชัดเจน' นั้นเห็นได้ชัดไม่น่าเกลียดและเป็นที่ยอมรับ แม้ว่าในภาษาดังกล่าว wildcard เป็นคุณสมบัติภาษาที่รองรับในขณะที่ใน Python มันเป็นตัวแปรจริงและได้รับการผูกไว้ซึ่งไม่น่าพอใจเล็กน้อย
โจ

4
สำหรับรายการประมวลผลภาษาซึ่งได้รับ Python นั้น access ;)list เช่นa[0], a[:](list copy), 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

หากวัตถุภายใน dictionary / tuple ของคุณเชื่อมโยงกันอย่างแน่นหนามันอาจเป็นความคิดที่ดีที่จะกำหนดคลาสให้กับมัน ด้วยวิธีนี้คุณจะสามารถกำหนดปฏิสัมพันธ์ระหว่างวัตถุประเภทนี้และให้ API เกี่ยวกับวิธีการทำงานกับพวกเขา คำถามทั่วไปที่ตามมา: ฉันควรใช้คลาสใน Python เมื่อใด .


4

ดูเหมือนจะเป็นทางเลือกที่ดีที่สุดสำหรับฉัน:

val1, val2, ignored1, ignored2 = some_function()

มันไม่ได้เป็นความลับหรือน่าเกลียด (เช่นวิธี func () [ดัชนี]) และระบุวัตถุประสงค์ของคุณอย่างชัดเจน


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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.