Bỏ qua python nhiều giá trị trả về


273

Giả sử tôi có hàm Python trả về nhiều giá trị trong một tuple:

def func():
    return 1, 2

Có một cách hay để bỏ qua một trong các kết quả thay vì chỉ gán cho một biến tạm thời? Nói rằng nếu tôi chỉ quan tâm đến giá trị đầu tiên, có cách nào tốt hơn thế này không:

x, temp = func()

2
Tôi đã tò mò về điều này cũng xuất phát từ khái niệm tương tự của Matlab về Bỏ qua các đầu ra chức năng nơi họ sử dụng ~làm cú pháp để bỏ qua một biến trả về cụ thể
jxramos

3
Bạn đã chọn câu trả lời sai làm giải pháp
AGP

Câu trả lời:


241

Một quy ước phổ biến là sử dụng "_" làm tên biến cho các thành phần của bộ dữ liệu bạn muốn bỏ qua. Ví dụ:

def f():
    return 1, 2, 3

_, _, x = f()

89
-1: "quy ước" này hút khi bạn thêm chức năng gettext vào mã của người khác (định nghĩa một hàm gọi là '_') vì vậy nó nên bị cấm
nosklo

27
Điểm hay - mặc dù vẫn còn tranh cãi liệu sự khăng khăng của gettext đối với việc cài đặt một chức năng gọi là " " có phải là một ý tưởng hay hay không. Cá nhân tôi thấy nó hơi xấu xí. Bất kể, việc sử dụng " " như một biến số vứt bỏ là phổ biến.
Brian Clapper

25
-1: _ có nghĩa là "đầu ra cuối cùng" trong IPython. Tôi sẽ không bao giờ chỉ định một cái gì đó cho nó.
endolith

20
Ok, tôi đã không chú ý đến "tôi" - cảm ơn đã tham khảo. IMHO bạn không thể mong đợi người khác không sử dụng biến chỉ vì một ứng dụng Python xác định cách sử dụng ma thuật của riêng mình cho nó.
Draemon

8
Một số IDE như PyDev sẽ đưa ra cảnh báo về điều này, bởi vì bạn có các biến không sử dụng.
teeks99

593

Bạn có thể sử dụng x = func()[0]để trả về giá trị đầu tiên, x = func()[1]để trả về giá trị thứ hai, v.v.

Nếu bạn muốn nhận được nhiều giá trị cùng một lúc, hãy sử dụng một cái gì đó như x, y = func()[2:4].


92
Đây phải là câu trả lời được chấp nhận. Bạn cũng có thể sử dụng những thứ như func()[2:4]nếu bạn chỉ muốn một số giá trị trả về.
endolith

11
Nó không gọi hàm nhiều lần: >>> def test (): ... in "tại đây" ... trả lại 1,2,3 ... >>> a, b = test () [: 2 ] ở đây [chỉnh sửa: xin lỗi rằng mã không được thông qua, vì vậy, bạn chỉ nhận được một dòng trong các nhận xét. Đối với những người không quen thuộc >>> và ... là sự khởi đầu của một dòng mới trong vỏ trăn]
teeks99

32
@TylerLong: Tôi nghĩ _, _, _, _, _, _, _, _, _, _, _, _, _, a, _, _, _, _, _, _, _, _, _, _, _, b, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, c, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, d, _, _, _, _, _, _, _, _, e, _ = func()không rõ ràng hơn việc gọi hàm nhiều lần, nhưng đó chỉ là ý kiến ​​của tôi. Nếu chức năng của bạn trả về nhiều mục đó, tôi nghĩ sử dụng numpy sẽ tốt hơn:a, b, c, d, e = func()[[13, 25, 58, 89, 98]]
endolith 26/03/13

24
@endolith Tôi nghĩ rằng điều này tốt hơn và không cần numpy và không cần gọi func () nhiều lần: result = func() a = result[13] b = result[25]...
Tyler Long

3
Đây là phong cách không thoải mái khi bạn muốn bỏ qua một hoặc một vài giá trị ở giữa, ví dụ:x, __, y = func()
ndemou

96

Nếu bạn đang sử dụng Python 3, bạn có thể sử dụng dấu sao trước một biến (ở bên trái của bài tập) để có danh sách trong việc giải nén.

# 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
Bạn cũng có thể sử dụng a, *_ = f()để bỏ qua số lượng giá trị trả về tùy ý sau a.
THN

21

Hãy nhớ rằng, khi bạn trả lại nhiều hơn một mục, bạn thực sự trả lại một tuple. Vì vậy, bạn có thể làm những việc như thế này:

def func():
    return 1, 2

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

17

Thực tiễn phổ biến là sử dụng biến giả _(dấu gạch dưới đơn), như nhiều người đã chỉ ra ở đây trước đây.

Tuy nhiên, để tránh xung đột với các cách sử dụng khác của tên biến đó (xem phản hồi này ), có thể nên sử dụng __(dấu gạch dưới kép) thay vào đó là một biến ném, như được chỉ ra bởi ncoghlan . Ví dụ:

x, __ = func()

Một ý kiến ​​không tồi chút nào. Nhưng sau đó '_ _' sẽ khai báo một biến trong không gian tên. Trong khi đó, '_' không khai báo trừ khi được sử dụng cụ thể ở phía bên trái của câu lệnh gán như trên (ví dụ a, _, _ = 1,8,9:). Cho đến thời điểm đó, nó lưu trữ kết quả của câu lệnh cuối cùng được thực thi mà nếu bạn muốn bắt, thông thường bạn sẽ sử dụng một biến để lưu trữ giá trị đó. Và đây là lý do tại sao, '_' là tên biến được đề xuất để bắt các giá trị rác. Các giá trị '_' được ghi đè ngay sau khi một câu lệnh khác được thực thi. Trong trường hợp '_ _', giá trị sẽ vẫn ở đó cho đến khi GC xóa sạch nó.
Archit Kapoor

16

Ba lựa chọn đơn giản.

Rõ ràng

x, _ = func()

x, junk = func()

Gớm

x = func()[0]

Và có nhiều cách để làm điều này với một trang trí.

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

func0= val0(func)

5
Tôi thực sự thích các _biến. Rõ ràng là bạn đang bỏ qua một giá trị
Claudiu

21
Ví dụ của bạn là ngược. x, _ = func()là gớm ghiếc, và x = func()[0]là hiển nhiên. Gán cho một biến và sau đó không sử dụng nó? Hàm đang trả về một tuple; lập chỉ mục nó như một tuple.
endolith

6
Trong các ngôn ngữ khớp mẫu, từ đó Python lấy được mẫu này, phương thức 'Rõ ràng' thực sự rõ ràng, không gớm ghiếc và kinh điển. Mặc dù, trong các ngôn ngữ như vậy, ký tự đại diện là một tính năng ngôn ngữ được hỗ trợ trong khi trong Python, đó là một biến thực và bị ràng buộc, điều này hơi khó chấp nhận.
Joe

4
Đối với các ngôn ngữ xử lý danh sách, từ đó Python có nguồn gốc ;), các trình truy cập danh sách như a[0], a[:](bản sao danh sách), a[::2](mỗi hai phần tử) và a[i:] + a[:i](xoay danh sách), thực sự, cũng rõ ràng và hợp quy.
cod3monk3y

7

Giải pháp tốt nhất có lẽ là đặt tên cho mọi thứ thay vì trả lại các bộ dữ liệu vô nghĩa. Trừ khi có một số logic đằng sau thứ tự của các mặt hàng được trả lại.

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

latitude = func()['lat']

Bạn thậm chí có thể sử dụng têntuple nếu bạn muốn thêm thông tin bổ sung về những gì bạn sẽ trả lại (nó không chỉ là một từ điển, đây là tọa độ):

from collections import namedtuple 

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

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

latitude = func().lat

Nếu các đối tượng trong từ điển / tuple của bạn được liên kết chặt chẽ với nhau thì đó có thể là một ý tưởng tốt để thậm chí xác định một lớp cho nó. Bằng cách đó, bạn cũng sẽ có thể xác định sự tương tác giữa các đối tượng thuộc loại này và cung cấp API về cách làm việc với chúng. Một câu hỏi tự nhiên sau: Khi nào tôi nên sử dụng các lớp trong Python? .


4

Đây dường như là sự lựa chọn tốt nhất với tôi:

val1, val2, ignored1, ignored2 = some_function()

Nó không khó hiểu hay xấu xí (như phương thức func () [index]) và nêu rõ mục đích của bạn.


4

Đây không phải là một câu trả lời trực tiếp cho câu hỏi. Thay vào đó, nó trả lời câu hỏi này: "Làm thế nào để tôi chọn một đầu ra chức năng cụ thể từ nhiều tùy chọn có thể?".

Nếu bạn có thể viết hàm (nghĩa là nó không có trong thư viện bạn không thể sửa đổi), sau đó thêm một đối số đầu vào cho biết bạn muốn gì ngoài hàm. Đặt nó làm đối số được đặt tên với giá trị mặc định để trong "trường hợp chung", bạn thậm chí không phải chỉ định nó.

    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 )

Phương pháp này cung cấp cho chức năng "cảnh báo nâng cao" liên quan đến đầu ra mong muốn. Do đó, nó có thể bỏ qua việc xử lý không cần thiết và chỉ thực hiện các công việc cần thiết để có được đầu ra mong muốn của bạn. Cũng bởi vì Python không gõ động, kiểu trả về có thể thay đổi. Lưu ý cách ví dụ trả về vô hướng, danh sách hoặc tuple ... bất cứ điều gì bạn thích!


2

Nếu đây là một hàm mà bạn sử dụng mọi lúc nhưng luôn loại bỏ đối số thứ hai, tôi sẽ lập luận rằng sẽ ít lộn xộn hơn khi tạo bí danh cho hàm mà không sử dụng giá trị trả về thứ hai lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

2

Khi bạn có nhiều đầu ra từ một hàm và bạn không muốn gọi nó nhiều lần, tôi nghĩ cách rõ ràng nhất để chọn kết quả sẽ là:

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

Như một ví dụ hoạt động tối thiểu, cũng chứng minh rằng hàm chỉ được gọi một lần:

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

Và các giá trị như mong đợi:

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

Để thuận tiện, các chỉ mục danh sách Python cũng có thể được sử dụng:

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

Trả về: a = 3 và b = 12

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.