Dấu gạch dưới hoặc gạch dưới [
for _ in range[5]:
print["Hello world"]
9] phục vụ nhiều mục đích trong Python và tôi đã nhầm lẫn về một số khía cạnh của từng mục đích trước khi bắt đầu bài viết này. Tôi đã đưa ra các giả định, đọc thông tin không chính xác và thậm chí nhận được một câu chuyện chưa hoàn chỉnh từ một lớp Python trực tuyến mà tôi đã tham giaTrong bài viết này, tôi sẽ trình bày cách sử dụng dấu gạch dưới và cho bạn lời khuyên rất thiên vị của tôi về cách xử lý nó
Trong bài viết này, tôi sẽ đề cập đến những cách sử dụng sau của
for _ in range[5]:
print["Hello world"]
9- Nó có thể được sử dụng như một biến tạm thời trong các vòng lặp và câu lệnh gán
- Cả dấu gạch dưới đơn [_______0_______9] và dấu gạch dưới kép [
for _ in range[5]:
2] đều có thể thêm vào trước một tên biến lớp để chỉ ra rằng biến đó phải ở chế độ riêng tư. Nó có giữ các biến của bạn ở chế độ riêng tư không?
print[_] - Nó có thể thêm tên chức năng để chỉ ra một chức năng nên riêng tư. Dấu gạch dưới có giữ chức năng của bạn ở chế độ riêng tư không?
for _ in range[5]:
print["Hello world"]
9 có thể được sử dụng thay cho biến "giả" cả trong vòng lặp và câu lệnh gán khi một hàm trả về nhiều giá trị và bạn muốn bỏ qua một hoặc nhiều giá trị trong số đóSử dụng trong vòng lặp
Nếu bạn cần Python thực hiện điều gì đó năm lần, cách rõ ràng nhất là sử dụng một biến giả trong vòng lặp for, như minh họa ở đây. Khi tôi đang sử dụng một biến giả, tôi khéo léo gọi nó là…
for _ in range[5]:
print[_]
4. Nhược điểm của cú pháp này được hiển thị bên dưới là tôi đã phải tạo một tên biến và hy vọng bất kỳ ai đọc mã của tôi đều hiểu rõ rằng tôi sẽ không bao giờ sử dụng lại for _ in range[5]:
print[_]
4Dễ dàng nhận thấy điều đó trong đoạn mã ngắn này, nhưng nếu vòng lặp dài hơn và phức tạp hơn thì nó sẽ ít rõ ràng hơn
for dummy in range[5]:
print["Hello world"]
Tôi có thể sử dụng
for _ in range[5]:
print["Hello world"]
9 để thay thế. Đoạn mã bên dưới sử dụng for _ in range[5]:
print["Hello world"]
9 để đạt được kết quả tương tự đồng thời báo hiệu cho bất kỳ ai đang đọc mã rằng tôi không có ý định sử dụng biến điều khiển vòng lặp ở bất kỳ đâu trong mã của mìnhfor _ in range[5]:
print["Hello world"]
Tôi thích cú pháp này và khuyến khích người khác sử dụng nó. Tuy nhiên, tôi không nhận ra rằng Python theo dõi giá trị của
for _ in range[5]:
print["Hello world"]
9 giống như bất kỳ biến nào khác. Hãy xem xét đoạn mã dưới đây; for _ in range[5]:
print[_]
Dấu gạch dưới thậm chí hoạt động trong một vòng lặp lồng nhau, nhưng việc theo dõi giá trị của biến
for _ in range[5]:
print["Hello world"]
9 trở nên khó hiểu hơn nhiều. Hãy xem xét vòng lặp này dưới đây. Bạn nghĩ mã này sẽ tạo ra cái gì? for _ in ['A','B','C']:
print[_, end=": "]
for _ in range[4]:
print[_, end=","] # what will this line print?
print[] # newline
Đây là đầu ra từ đoạn mã trên
A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
Có thể đầu ra ở trên không làm bạn ngạc nhiên, nhưng nó làm tôi ngạc nhiên. Bạn nghĩ giá trị nào mà
for _ in range[5]:
print["Hello world"]
9 đại diện khi các vòng lặp for lồng nhau hoàn tất? for _ in ['A','B','C']:
pass
for _ in range[4]:
passprint[_] # what will this line print?
Tôi rất ngạc nhiên khi mã ở trên được in
for _ in ['A','B','C']:
print[_, end=": "]
for _ in range[4]:
print[_, end=","] # what will this line print?
print[] # newline
4. Tôi mong đợi nó không hợp lệ hoặc in for _ in ['A','B','C']:
print[_, end=": "]
for _ in range[4]:
print[_, end=","] # what will this line print?
print[] # newline
5. Những gì đang xảy ra thực sự khá đơn giản. Mỗi lần lặp của vòng lặp for đang gán for _ in range[5]:
print["Hello world"]
9 cho giá trị tiếp theo trong trình vòng lặp. Vòng lặp for bên ngoài chỉ đơn giản gán for _ in range[5]:
print["Hello world"]
9 cho giá trị tiếp theo trong for _ in ['A','B','C']:
print[_, end=": "]
for _ in range[4]:
print[_, end=","] # what will this line print?
print[] # newline
8 và vòng lặp for bên trong gán for _ in range[5]:
print["Hello world"]
9 cho giá trị tiếp theo trong trình vòng lặp A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
0Sự nhầm lẫn này dẫn tôi đến lời khuyên đầu tiên
Không bao giờ sử dụng dấu gạch dưới làm đầu vào cho một chức năng hoặc thao tác. Nếu bạn cần theo dõi một biến, hãy dành thời gian đặt cho nó một cái tên mô tả
Bỏ qua giá trị trả về
Một số hàm Python trả về nhiều giá trị, nhưng tôi thường không cần tất cả các giá trị đó.
for _ in range[5]:
print["Hello world"]
9 chỉ ra rằng tôi đang bỏ qua giá trị đó. Giả sử chúng ta có một hàm trả về giá trị trung bình, chế độ và độ lệch chuẩn của tập dữ liệu, nhưng hiện tại chúng ta chỉ quan tâm đến độ lệch chuẩn. Chúng ta có thể viết như sau_, _, stdev = myfunction[large_dataset]
Đoạn mã trên cho bất kỳ ai đọc mã của tôi biết rằng tôi chỉ định sử dụng một trong ba giá trị được trả về bởi
A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
2. Tôi thích cú pháp này hơn là khai báo thêm hai biến không bao giờ được sử dụng. Tuy nhiên, đằng sau hậu trường, Python lưu trữ giá trị của for _ in range[5]:
print["Hello world"]
9 — nhưng giá trị nào? _, _, stdev = myfunction[large_dataset]
print[_] # what will this line print?
Đoạn mã trên sẽ hiển thị giá trị thứ hai được trả về bởi
A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
2. Tôi không biết điều gì sẽ xảy ra cho đến khi tôi thử nghiệm nó trong Python REPL như thế này>>> _, _, stdev = [1, 2, 3]
>>> print[_]
2
Sự nhầm lẫn này khiến tôi phải sửa lại lời khuyên mà tôi đã đưa ra trước đó một chút
2. Dấu gạch dưới để chỉ ra các thuộc tính của lớp là riêng tưSử dụng dấu gạch dưới để bỏ qua một giá trị được trả về bởi hàm. Không bao giờ sử dụng dấu gạch dưới làm đầu vào cho một chức năng hoặc hoạt động. Nếu bạn cần theo dõi một biến, hãy dành thời gian đặt cho nó một cái tên mô tả
Sử dụng các tín hiệu gạch dưới cho những người đọc và sử dụng mã, bạn có ý định đặt một biến ở chế độ riêng tư, nhưng thật đáng buồn là Python không thực thi ý định của bạn. Hãy xem xét lớp Python vô lý sau đây định nghĩa hai biến cục bộ, một biến được thêm vào trước bởi một dấu gạch dưới và biến kia có hai dấu gạch dưới
class MyClass:
def __init__[self]:
self._myprivate = 12
self.__myreallyprivate = 42
Bất kỳ ai sử dụng lớp này đều có thể dễ dàng truy cập trực tiếp các biến này, mặc dù tôi dự định đặt các biến đó ở chế độ riêng tư. Python xử lý dấu gạch dưới đơn và dấu gạch dưới kép khác nhau [tôi sẽ giải thích điều đó ngay sau đây], nhưng không có cách nào trong Python thực sự đặt một biến lớp ở chế độ riêng tư như bạn có thể làm trong Java hoặc C++. Hai dòng mã sau đây sẽ chỉ ra rằng cả hai biến đều có thể được đọc và ghi trực tiếp
for _ in range[5]:
print["Hello world"]
0Danh sách
A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
6 của thể hiện lớp cho thấy rằng sự khác biệt duy nhất giữa A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
7 [dấu gạch dưới đơn] và A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
8 [dấu gạch dưới kép] là A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
8 hơi bị xáo trộn. Tôi có thể ghi đè lên cả hai biến mà tác giả dự định ban đầu là riêng tư như thế nàyfor _ in range[5]:
print["Hello world"]
1Có lẽ bạn đang thắc mắc mục đích che giấu của
A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
8 có thể là gì nếu nó có thể dễ dàng được phát hiện bằng một A: 0,1,2,3,
B: 0,1,2,3,
C: 0,1,2,3,
6 đơn giản hoặc bằng cách đọc tài liệu Python. Việc che giấu này có ích khi bạn tạo các lớp con có cùng tên biến cục bộTôi sẽ minh họa điều này bằng một ví dụ đơn giản hơn về lớp cha và lớp con mà cả hai đều triển khai biến
for _ in ['A','B','C']:2. Xem xét các định nghĩa lớp sau
pass
for _ in range[4]:
passprint[_] # what will this line print?
for _ in range[5]:
print["Hello world"]
2Lớp con ở trên sẽ có hai biến bị xáo trộn. Tôi có thể hiển thị các biến đó bằng đoạn mã sau
for _ in range[5]:
print["Hello world"]
3Những quan sát về dấu gạch dưới đơn và kép trong tên biến lớp dẫn tôi đến một số lời khuyên
Nếu bạn là tác giả của một lớp
- Cung cấp phương thức “get” cho từng biến cục bộ mà bạn dự định người tiêu dùng trong lớp của bạn sẽ đọc
- Sử dụng dấu gạch dưới để chỉ ra rằng các biến nên được coi là riêng tư
Nếu bạn là người tiêu dùng của một lớp mà người khác đã viết
- Tránh truy cập trực tiếp các biến cục bộ của lớp nếu có thể
- Tuyệt đối tránh truy cập trực tiếp các biến lớp được thêm dấu gạch dưới vào trước bằng mọi giá. Tác giả đặt dấu gạch dưới [hoặc cặp dấu gạch dưới] ở đó là có lý do
Giống như với các biến lớp,
for _ in range[5]:
print["Hello world"]
9 được sử dụng để báo hiệu ý định đặt một hàm ở chế độ riêng tư, nhưng Python cũng không thực thi điều này. Hãy xem xét một tệp Python có tên for _ in ['A','B','C']:4 với định nghĩa hàm sau
pass
for _ in range[4]:
passprint[_] # what will this line print?
for _ in range[5]:
print["Hello world"]
4Nếu tôi nhập mô-đun Python này bằng một câu lệnh nhập chung như
for _ in ['A','B','C']:5, thì tôi vẫn có thể dễ dàng truy cập các mô-đun mà tôi đã cố gắng đánh dấu là riêng tư. Đó hoàn toàn không phải là những gì tác giả của hàm
pass
for _ in range[4]:
passprint[_] # what will this line print?
for _ in ['A','B','C']:6 dự định
pass
for _ in range[4]:
passprint[_] # what will this line print?
for _ in range[5]:
print["Hello world"]
5Bất kỳ chức năng nào - ngay cả những chức năng riêng tư - đều có thể được nhập một cách rõ ràng, như được hiển thị bên dưới. Một lần nữa, đây hoàn toàn không phải là ý định của tác giả hàm
for _ in ['A','B','C']:6
pass
for _ in range[4]:
passprint[_] # what will this line print?
for _ in range[5]:
print["Hello world"]
6Tôi thậm chí có thể tạo bí danh cho chức năng riêng tư, vì vậy tôi không bị nhắc nhở liên tục rằng tôi đang sử dụng chức năng riêng tư
for _ in range[5]:
print["Hello world"]
7Thật thú vị, lần duy nhất chức năng riêng tư không được nhập là khi ký tự đại diện được sử dụng, nhưng các nguyên tắc về kiểu dáng không khuyến khích sử dụng ký tự đại diện vì nó có thể tạo ra xung đột hoặc nhầm lẫn trong không gian tên
for _ in range[5]:
print["Hello world"]
8Bất kể những gì Python cho phép và không cho phép, lời khuyên cuối cùng của tôi là
Suy nghĩ cuối cùngMặc dù Python không ngăn bạn làm như vậy, nhưng hãy tránh nhập một hàm đã được đánh dấu là riêng tư
Tất cả lời khuyên của tôi về
for _ in range[5]:
print["Hello world"]
9 đều tập trung vào việc báo hiệu ý định của bạn khi viết mã và tôn trọng ý định của người khác khi sử dụng mã của họ. Tuy nhiên, tôn trọng ý định của các tác giả khác hoàn toàn không phải là lịch sự. Lời khuyên này là về việc bảo vệ chính bạnCác ví dụ tôi đưa ra trong bài viết này rất đơn giản và dễ làm theo. Khi bạn sử dụng mã phức tạp hơn, có thể có những hành vi mà bạn không lường trước được. Hàm riêng tư hoặc biến riêng tư có thể hoạt động khác với mong đợi của bạn trong một số trường hợp góc
Hơn nữa, việc triển khai các biến hoặc chức năng đó có thể thay đổi trong các phiên bản mã trong tương lai. Rốt cuộc, tác giả của mã đó đã đánh dấu chúng là riêng tư và do đó có thể tự do thay đổi chúng bất kỳ lúc nào