Mục đích của biến gạch dưới dấu gạch dưới đơn trong Python là gì?


618

Ý nghĩa của _sau fortrong mã này là gì?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1


5
Đối với trường hợp của bạn, nó sẽ sạch hơn len(tbh.bag.atom_set())(nếu giá trị được trả về có __len__phương thức) hoặcsum(1 for _ in tbh.bag.atom_set())
Nick T

Trong pylintmột tùy chọn khác cho tên biến giả là tiền tố của dummy_tên biến. Sử dụng tiền tố này với pylint, làm cho pylintkhông phát ra cảnh báo. Ngoài ra, bạn có thể định cấu hình mô hình biến giả pylintđể chứa những thứ như thế __.
Trevor Boyd Smith

Câu trả lời:


780

_ có 4 cách sử dụng thông thường chính trong Python:

  1. Để giữ kết quả của biểu thức (/ câu lệnh) được thực hiện cuối cùng trong phiên phiên dịch tương tác. Tiền lệ này được thiết lập bởi trình thông dịch CPython tiêu chuẩn và các thông dịch viên khác đã làm theo
  2. Để tra cứu bản dịch trong i18n (xem tài liệu gettext chẳng hạn), như trong mã như: raise forms.ValidationError(_("Please enter a correct username"))
  3. Là một tên biến "mục đích" chung để chỉ ra rằng một phần của kết quả hàm đang bị bỏ qua một cách có chủ ý (Về mặt khái niệm, nó đang bị loại bỏ.), Như trong mã như : label, has_label, _ = text.partition(':').
  4. Là một phần của định nghĩa hàm (sử dụng một trong hai defhoặc lambda), trong đó chữ ký được cố định (ví dụ: bằng hàm gọi lại hoặc API lớp cha), nhưng việc triển khai hàm cụ thể này không cần tất cả các tham số, như trong mã như:callback = lambda _: True

(Trong một thời gian dài, câu trả lời này chỉ liệt kê ba trường hợp sử dụng đầu tiên, nhưng trường hợp thứ tư thường xuất hiện đủ, như đã lưu ý ở đây , để có giá trị liệt kê rõ ràng)

Các trường hợp sử dụng "biến số hoặc tên tham số" sau này có thể xung đột với trường hợp sử dụng tra cứu dịch thuật, do đó, cần tránh sử dụng _như một biến ném trong bất kỳ khối mã nào cũng sử dụng nó cho bản dịch i18n (nhiều người thích sử dụng dấu gạch dưới kép ,, __như là biến số bỏ đi của họ cho chính xác lý do này).


19
Bạn có thể giải thích cách thức hoạt động của nó trong một cuộc gọi chức năng, ví dụ: nâng biểu mẫu.ValidationError (_ ("Vui lòng nhập tên người dùng chính xác")) . Tôi đã thấy mã này trong mã Django và không rõ chuyện gì đang xảy ra.
John C

41
Đó là cách sử dụng 2 - theo quy ước, _là tên được sử dụng cho chức năng tìm kiếm bản dịch chuỗi quốc tế hóa và bản địa hóa. Tôi khá chắc chắn rằng gettextthư viện C đã thiết lập quy ước đó.
ncoghlan

43
FWIW, cá nhân tôi đã bắt đầu sử dụng __(một dấu gạch dưới kép) làm biến số vứt bỏ mục đích chung của tôi để tránh xung đột với một trong hai trường hợp sử dụng đầu tiên.
ncoghlan

14
Các quy ước cộng đồng mới nổi không có xu hướng có các nguồn có thẩm quyền - chỉ quan sát các thực tiễn đã xuất hiện theo thời gian. FWIW, tôi là một trong những đồng tác giả của các bản cập nhật PEP 8 gần đây hơn và câu trả lời của tôi dựa trên 3 cách khác nhau mà tôi thấy _được sử dụng làm tên biến kể từ khi tôi bắt đầu sử dụng Python một cách chuyên nghiệp vào năm 2002.
ncoghlan

12
Quy ước chủ yếu dành cho việc giải nén bộ dữ liệu: a, __, c = iterablecho người đọc biết ngay lập tức rằng chúng tôi đang giải nén bộ 3, nhưng chỉ sử dụng các giá trị đầu tiên và cuối cùng. Nếu chúng ta thay vì viết a, b, c = iterable, người đọc (hoặc một Linter đang tự động) một cách hợp lý có thể mong đợi tất cả a, bcsẽ được sử dụng sau đó (và nếu họ không, nó có thể là một dấu hiệu của một đâu đó bug).
ncoghlan

207

Nó chỉ là một tên biến và thông thường trong python được sử dụng _cho các biến số bỏ đi. Nó chỉ ra rằng biến vòng lặp không thực sự được sử dụng.


5
bạn có nghĩa là nó không đại diện cho giá trị trả lại cuối cùng?
alwbtc

31
@steve chỉ trong vỏ
Gabi Purcaru

4
tương tự như việc sử dụng _ trong Prolog
Matthias

3
tương tự như việc sử dụng ~ trong Matlab
PatriceG

Lưu ý rằng trong trình bao cpython nếu bạn xác định rõ ràng _, nó sẽ dừng vĩnh viễn việc giữ giá trị đầu ra của biểu thức trước đó. Điều này có vẻ không nhất quán khủng khiếp và các tiêu chuẩn lang Python cần giải quyết vấn đề này. Họ chỉ nên định nghĩa _là một tên vứt đi và ngăn không cho nó được sử dụng như một định danh thực sự.
theferrit32

78

Dấu gạch dưới _được coi là biến " Tôi không quan tâm " hoặc " Ném đi " trong Python

  • Trình thông dịch python lưu giá trị biểu thức cuối cùng vào biến đặc biệt được gọi _.

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
  • Dấu gạch dưới _cũng được sử dụng để bỏ qua các giá trị cụ thể. Nếu bạn không cần các giá trị cụ thể hoặc các giá trị không được sử dụng, chỉ cần gán các giá trị cho dấu gạch dưới.

    Bỏ qua một giá trị khi giải nén

    x, _, y = (1, 2, 3)
    
    >>> x
    1
    
    >>> y 
    3

    Bỏ qua chỉ số

    for _ in range(10):     
        do_something()

2
Có cách sử dụng thứ ba, dành cho chức năng quốc tế hóa _("Hello world!").
Jeff Younker

3
Ở cấp độ bộ xử lý, có thực sự có sự khác biệt giữa "cho _ trong phạm vi" và "cho x trong phạm vi" và sau đó không sử dụng x? Hay nó chỉ dành cho khả năng đọc của con người?
iammax

1
@iammax Sử dụng dismô-đun tôi thấy không có sự khác biệt trong mã byte. Những lợi ích của khả năng đọc của con người là rõ ràng, tuy nhiên.
Alistair Carscadden

21

Có 5 trường hợp sử dụng dấu gạch dưới trong Python.

  1. Để lưu trữ giá trị của biểu thức cuối cùng trong trình thông dịch.

  2. Để bỏ qua các giá trị cụ thể. (cái gọi là tôi không quan tâm

  3. Để cung cấp ý nghĩa đặc biệt và chức năng cho tên của vartiable hoặc chức năng.

  4. Để sử dụng như các chức năng 'Quốc tế hóa (i18n)' hoặc 'Bản địa hóa (l10n)'.

  5. Để tách các chữ số của giá trị chữ.

Đây là một bài viết tốt với các ví dụ của mingrammer .


2
Trên thực tế, nó khá mới, blog.pythonl Library.org/2017/01/11/ Khăn
MichaelChirico

3

Đối với các ngôn ngữ Python có liên quan, _không có ý nghĩa đặc biệt. Nó là một định danh hợp lệ giống như _foo, foo_hoặc _f_o_o_.

Bất kỳ ý nghĩa đặc biệt của _là hoàn toàn theo quy ước. Một số trường hợp là phổ biến:

  • Tên giả khi một biến không được sử dụng, nhưng tên được yêu cầu theo cú pháp / ngữ nghĩa.

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • Nhiều REPL / shell lưu trữ kết quả của biểu thức cấp cao nhất cuối cùng tới builtins._.

    Mã định danh đặc biệt _được sử dụng trong trình thông dịch tương tác để lưu trữ kết quả của lần đánh giá cuối cùng; nó được lưu trữ trong builtinsmô-đun. Khi không ở chế độ tương tác, _không có ý nghĩa đặc biệt và không được xác định. [ nguồn ]

    Do cách nhìn tên, trừ khi bị che khuất bởi một _định nghĩa toàn cầu hoặc địa phương mà trần _đề cập đến builtins._.

    >>> 42
    42
    >>> f'the last answer is {_}'
    'the last answer is 42'
    >>> _
    'the last answer is 42'
    >>> _ = 4  # shadow ``builtins._`` with global ``_``
    >>> 23
    23
    >>> _
    4

    Lưu ý: Một số shell như ipythonkhông gán cho builtins._nhưng trường hợp đặc biệt _.

  • Trong bối cảnh quốc tế hóa và bản địa hóa, _được sử dụng như một bí danh cho chức năng dịch chính.

    gettext.gettext (tin nhắn)

    Trả về bản dịch tin nhắn được bản địa hóa, dựa trên thư mục tên miền, ngôn ngữ và ngôn ngữ toàn cầu hiện tại. Hàm này thường được đặt bí danh là _ () trong không gian tên cục bộ (xem ví dụ bên dưới).

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.