Python của lambda với dấu gạch dưới cho một đối số?


84

Đoạn mã sau làm gì?

a = lambda _:True

Từ những gì tôi đọc và thử nghiệm trong dấu nhắc tương tác, nó dường như là một hàm luôn trả về True.

Tôi hiểu điều này có đúng không? Tôi hy vọng hiểu tại sao dấu gạch dưới ( _) cũng được sử dụng.


10
Đối với những gì một lambda parameterless, cú pháp làlambda : True
Robino

17
Điều tôi không thích về bài đăng này là tiêu đề câu hỏi nói về một hàm lambda " KHÔNG có biến", nhưng phần nội dung câu hỏi và hầu như tất cả các câu trả lời, đưa ra ví dụ về một hàm lambda có một biến / đối số. Biến đó chỉ xảy ra với một tên lạ _, thay vì xhoặc ahoặc bất cứ điều gì. Nếu ai đó muốn biết cách viết một hàm lambda không có đối số; đây là cách: Xác định nó như thế này: my_lambda = lambda : 255. Gọi nó như thế này: x = my_lambda()Bạn có thể thay thế 255bằng bất kỳ giá trị trả lại nào bạn thích.
Toothpick Anemone

2
@ToothpickAnemone trả lời tuyệt vời! Tôi chủ yếu sử dụng lambda mà không có biến để khởi tạo các lệnh mặc định ngày nay. hy vọng nó hữu ích cho những người đọc chủ đề này. ht = {} ht = defaultdict (lambda: 0, ht)
laycat

Câu trả lời:


143

Tên _biến là. Thử nó. (Tên biến này thường là tên cho một biến bị bỏ qua. Có thể nói là một trình giữ chỗ.)

Python:

>>> l = lambda _: True
>>> l()
<lambda>() missing 1 required positional argument: '_'

>>> l("foo")
True

Vì vậy, lambda này yêu cầu một đối số . Nếu bạn muốn một lambda không có đối số luôn trả về True, hãy làm như sau:

>>> m = lambda: True
>>> m()
True

7
@dopatraman đã thử nghiệm nó với Python 3.6.2under Mac OS 10.12và nó hoạt động.
winklerrr

6
Có thể bạn có thể thêm thông tin mà tên _biến thường được sử dụng khi bản thân biến đó không thực sự cần thiết. Nó giống như một "biến loại bỏ", chỉ là một trình giữ chỗ không có giá trị sử dụng.
winklerrr

1
@dopatraman Trong Ipython, _ giữ giá trị được trả về bởi biểu thức cuối cùng. Tôi tránh sử dụng _ vì lý do này. stackoverflow.com/questions/17580289/…
Taro Kiritani vào

7

Dấu gạch dưới là một quy ước Python để đặt tên cho một biến không sử dụng (ví dụ: các công cụ phân tích tĩnh không báo cáo nó là biến không sử dụng). Trong trường hợp của bạn, đối số lambda không được sử dụng, nhưng đối tượng được tạo là một hàm đối số luôn trả về True. Vì vậy, lambda của bạn hơi tương tự với Hàm hằng trong toán học.


không chỉ trăn chuyển đổi, đó là một ngôn ngữ-agnostic và gạch được sử dụng để chỉ ra rằng một biến là tạm thời hoặc không đáng kể
Sławomir Lenart

6

nó dường như là một hàm trả về True bất kể.

Đúng, nó là một hàm (hoặc lambda) trả về True. Dấu gạch dưới , thường là chỗ dành sẵn cho một biến bị bỏ qua, là không cần thiết trong trường hợp này.

Một trường hợp sử dụng ví dụ cho một hàm như vậy (hầu như không có gì):

dd = collections.defaultdict(lambda: True)

Khi được sử dụng như là đối số đến một defaultdict , bạn có thể có Truenhư một giá trị mặc định chung.


4

Lambda có nghĩa là một hàm. Câu lệnh trên cũng giống như cách viết

def f(_):
    return True

Đối với lambda, một biến cần phải có. Vì vậy, bạn chuyển cho nó một biến có tên _(Tương tự như vậy, bạn có thể truyền x, y..)


3

Dấu gạch dưới _là một định danh hợp lệ và được sử dụng ở đây như một tên biến. Nó sẽ luôn trả về Trueđối số được truyền vào hàm.

>>>a('123') 
True

Xin chào, cảm ơn vì đã trả lời nhanh chóng. vậy nó là một hàm ẩn danh luôn trả về true?
laycat

@laycat; Đúng. Nó sẽ luôn trả về true.
haccks

2

Dưới đây là dòng mã được đề cập:

a = lambda _:True

Nó tạo ra một hàm có tham số một đầu vào: _. Dấu gạch dưới là một lựa chọn khá lạ của tên biến, nhưng nó chỉ là một tên biến. Bạn có thể sử dụng ở _bất cứ đâu, ngay cả khi không sử dụng các hàm lambda. Ví dụ, thay vì….

my_var = 5
print(my_var)

Bạn có thể viết:

_ = 5
print(_)

Tuy nhiên, có một lý do _đã được sử dụng làm tên của tên tham số thay vì một cái gì đó như xhoặc input. Chúng tôi sẽ đạt được điều đó trong giây lát.

Trước tiên, chúng ta cần biết rằng từ khóa lambda xây dựng một hàm, tương tự như def, nhưng với cú pháp khác. Định nghĩa của hàm lambda a = lambda _:True, tương tự như cách viết:

def a(_):
    return True

Nó tạo ra một hàm có tên avới một tham số đầu vào _và nó sẽ trả về True. Người ta có thể viết dễ dàng như vậy a = lambda x:True, với một xthay vì một dấu gạch dưới. Tuy nhiên, quy ước là sử dụng _như một tên biến khi chúng ta không có ý định sử dụng biến đó. Hãy xem xét những điều sau:

for _ in range(1, 11):
    print('pear')

Lưu ý rằng chỉ mục vòng lặp không bao giờ được sử dụng bên trong thân vòng lặp. Chúng tôi chỉ muốn vòng lặp thực thi một số lần xác định. Như winklerrrđã viết, "tên biến _là [...] giống như một" biến loại bỏ ", chỉ là một trình giữ chỗ không có giá trị sử dụng."

Tương tự như vậy, với `` a = lambda x: True , tham số đầu vào không được sử dụng bên trong phần thân của hàm. Đối số đầu vào là gì không thực sự quan trọng, miễn là có một đối số. Tác giả của hàm lambda đó đã viết _thay vì một cái gì đó như thế x, để chỉ ra rằng biến sẽ không được sử dụng.

Lưu ý rằng lambda không có một cuộc tranh cãi; Vì vậy, viết

a(), sẽ phát sinh lỗi.

Nếu bạn muốn một lambda không có đối số, hãy viết một cái gì đó như sau:

 bar = lambda: True

Bây giờ gọi bar(), không có args, sẽ hoạt động tốt. Một lambda không nhận đối số không nhất thiết phải luôn trả về cùng một giá trị:

import random
process_fruit = lambda : random.random()

Hàm lambda ở trên phức tạp hơn, chỉ là một cái gì đó luôn trả về cùng một hằng số.

Một lý do mà các lập trình viên đôi khi sử dụng lambdatừ khóa thay vì def cho các hàm đặc biệt ngắn và đơn giản. Lưu ý rằng một lambdađịnh nghĩa thường có thể phù hợp với tất cả trên một dòng, ngược lại, rất khó để làm điều tương tự với một câu lệnh def. Một lý do khác để sử dụng lambdathay cho defsf khi hàm sẽ không được sử dụng nữa. Nếu sau này chúng ta không muốn gọi lại hàm, thì không cần đặt tên cho hàm. Ví dụ, hãy xem xét đoạn mã sau:

def apply_to_each (biến đổi, in_container): out_container = list () cho idx, item trong enumerate (container, 0): out_container [idx] = biến đổi (item) return out_container

Bây giờ chúng tôi thực hiện cuộc gọi sau:

squares  = apply_to_each(lambda x: x**2 range(0, 101))

Lưu ý rằng lambda x: x**2không được đưa ra một nhãn. Điều này là do chúng tôi có thể sẽ không gọi nó lại sau này, nó chỉ là một cái gì đó ngắn gọn và đơn giản mà chúng tôi cần tạm thời.

Thực tế là các hàm lambda không cần đặt tên là nguồn gốc của một tên khác để mô tả chúng: "các hàm ẩn danh".

Cũng lưu ý rằng các câu lệnh lambda giống như một lời gọi hàm trong đó chúng trả về một tham chiếu đến hàm mà chúng tạo ra. Sau đây là bất hợp pháp:

apply_to_each(def foo(x): x**2 ,  range(0, 101))

Trong khi đó, apply_to_each(lambda x: x**2 range(0, 101))là tốt.

Vì vậy, chúng tôi sử dụng lambdathay vì def_thay vì một tên biến dài khi chúng tôi muốn một cái gì đó ngắn gọn, ngọt ngào và có thể sẽ không muốn sử dụng lại sau này.

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.