sách gpt4 ăn đã đi

Hướng dẫn phong cách mã hóa Python nội bộ của Google

In lại Tác giả: qq735679552 Thời gian cập nhật: 28-09-2022 22:32:09 40 4
mua khóa gpt4 giày nike

CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.

Bài viết trên blog CFSDN này Hướng dẫn phong cách mã hóa Python nội bộ của Google được tác giả sưu tầm và biên soạn. Nếu bạn quan tâm đến bài viết này, hãy nhớ thích nó.

  。

Đây là hướng dẫn về kiểu mã Google Python do một người bạn dịch, rất toàn diện. Nó có thể được sử dụng làm tiêu chuẩn đánh giá mã của công ty hoặc làm hướng dẫn về phong cách viết mã của riêng bạn. Hy vọng nó sẽ giúp bạn.

Người dịch: shendeguize@github 。

Liên kết: https://github.com/shendeguize/GooglePythonStyleGuideCN 。

Bản dịch này bị giới hạn bởi mức độ của nó và có thể có những điểm không chính xác. Xin vui lòng chỉ ra. Cảm ơn tất cả các bạn.

1. Bối cảnh

  。

Python là ngôn ngữ động chính được Google sử dụng. Hướng dẫn phong cách này liệt kê những điều nên và không nên làm khi lập trình bằng Python.

Để giúp bạn sắp xếp mã của mình một cách chính xác, chúng tôi đã viết tệp cài đặt Vim. Đối với Emacs, cài đặt mặc định là đủ.

Nhiều nhóm sử dụng công cụ định dạng tự động yapf để tránh tranh chấp về định dạng.

2. Quy tắc ngôn ngữ Python

  。

2.1 Xơ vải

Sử dụng pylint cho mã của bạn.

2.1.1Định nghĩa (sau đây gọi là định nghĩa).

pylint là một công cụ để tìm lỗi và các vấn đề về kiểu mã hóa trong mã Python. pylint tìm kiếm các vấn đề thường gặp trong trình biên dịch cho các ngôn ngữ không động (chẳng hạn như C hoặc C++). không có mặt. Đúng, nhưng sẽ có rất ít cảnh báo lỗi.

2.1.2 Ưu điểm 。

Có thể tìm thấy một số lỗi dễ bị bỏ qua như lỗi chính tả, lỗi gọi sớm hơn khai báo, v.v..

2.1.3 Nhược điểm 。

pylint không hoàn hảo. Để sử dụng công cụ này tốt hơn, đôi khi chúng ta cần đến nó.

a. Viết xung quanh nó (thích ứng với phong cách ngữ cảnh).

b. Loại bỏ một số cảnh báo.

c. Công cụ tối ưu hóa.

2.1.4 Quyết định (sau đây dịch là kiến ​​nghị).

Đảm bảo áp dụng pylint cho mã của bạn.

Nếu một số cảnh báo không phù hợp, hãy chặn những cảnh báo này để các cảnh báo khác không bị ẩn. Để chặn các cảnh báo, bạn có thể đặt nhận xét ở cấp độ dòng.

  1. từ điển = 'một cái gì đó khủng khiếp'  # Ý tưởng tồi... pylint: vô hiệu hóa=được định nghĩa lại-tích hợp sẵn 

cảnh báo pylint chứa số nhận dạng (chuỗi tài liệu trống), cảnh báo dành riêng cho Google bắt đầu bằng g-.

Nếu lý do chặn cảnh báo không đủ rõ ràng trong tên thẻ, hãy thêm nhận xét bổ sung.

Ưu điểm của việc loại bỏ các cảnh báo theo cách này là chúng ta có thể dễ dàng tìm thấy các cảnh báo bị loại bỏ và xem lại chúng.

Bạn có thể nhận được danh sách các cảnh báo pylint bằng cách:

  1. pylint --danh sách-tin nhắn 

Sử dụng các phương pháp sau để biết thêm thông tin cụ thể về một tin nhắn cụ thể

  1. trụ cột --trợ giúp-tin nhắn=C6409 

Thích sử dụng pylint: vô hiệu hóa thay vì phương thức cũ (pylint: vô hiệu hóa thông báo). Nếu bạn muốn chặn cảnh báo do các tham số không được sử dụng, bạn có thể xóa ở đầu hàm và nhận xét lý do tại sao bạn muốn xóa các tham số không sử dụng này. "không sử dụng" là chưa đủ

  1. def viking_cafe_order(spam, đậu, trứng=Không có):  
  2.     đậu del, trứng # Không được người Viking sử dụng.  
  3.     trả lại thư rác + thư rác + spa 

Các phương pháp khác có thể được sử dụng để chặn cảnh báo bao gồm sử dụng '_' làm mã định danh cho các tham số không được sử dụng, thêm 'unused_' trước tên tham số hoặc gán các tham số này cho '_'. Các phương pháp này được cho phép nhưng việc tiếp tục sử dụng chúng không được khuyến khích. Hai phương thức đầu tiên sẽ ảnh hưởng đến phương thức gọi truyền tham số thông qua tên tham số và phương thức cuối cùng không đảm bảo rằng các tham số thực sự không được sử dụng.

2.2 Nhập khẩu

Chỉ sử dụng tính năng nhập khi nhập các gói và mô-đun và không áp dụng cho các lớp hoặc hàm riêng lẻ (Điều này đặc biệt đáng ngạc nhiên đối với việc gõ_module).

2.2.1 Định nghĩa.

Cơ chế tái sử dụng để chia sẻ mã từ mô-đun này sang mô-đun khác.

2.2.2 Ưu điểm 。

Quy ước quản lý không gian tên rất đơn giản và nguồn của mỗi mã định danh được chỉ định một cách nhất quán. Ví dụ: x.Obj có nghĩa là Obj được xác định trong mô-đun x.

2.2.3 Nhược điểm 。

Tên mô-đun có thể xung đột và một số tên mô-đun có thể rất dài, điều này gây bất tiện.

2.2.4 Khuyến nghị.

  •  nhập x (khi x là gói hoặc mô-đun)
  •  from x import y (khi x là tiền tố gói và y là tên mô-đun không có tiền tố)
  •  from x import y as z (khi có tên mô-đun trùng lặp y hoặc y quá dài để tham chiếu)
  •  nhập y dưới dạng z (chỉ được sử dụng như một cách viết tắt rất chung chung, ví dụ: nhập numpy dưới dạng np)

Lấy sound.effect.echo làm ví dụ

  1. từ sound.effects nhập echo...echo.EchoFilter(đầu vào, đầu ra, trì hoãn=0.7, chú ý=4

Không sử dụng các tham chiếu tương đối Ngay cả trong cùng một gói, hãy sử dụng tên gói đầy đủ để nhập. Điều này giúp tránh các gói nhập trùng lặp ngoài ý muốn.

Các quy tắc trên không áp dụng từ việc nhập mô-đun gõ và nhập mô-đun six.moves.

2.3 Gói

Mỗi mô-đun phải được nhập từ đường dẫn đầy đủ.

2.3.1 Ưu điểm 。

Nó có thể tránh xung đột tên mô-đun và tham chiếu không chính xác do đường dẫn tìm kiếm mô-đun không phù hợp với mong đợi của tác giả.

2.3.2 Nhược điểm 。

Việc triển khai mã hơi khó khăn vì kiến ​​trúc gói cũng cần được gán giá trị, nhưng với cơ chế triển khai hiện tại thì đây không phải là vấn đề.

2.3.3 Khuyến nghị.

Tất cả mã mới phải nhập mô-đun từ tên gói đầy đủ.

Ví dụ nhập sẽ trông như thế này

Đúng

  1. # Tham chiếu absl.flags trong mã với tên đầy đủ (chi tiết).  
  2. # Gọi absl.flags bằng đường dẫn đầy đủ trong mã  
  3. nhập absl.flagsfrom doctor.who nhập jodie  
  4. CỜ = tuyệt đối.cờ.CỜ 
  1. # Tham chiếu cờ trong mã chỉ bằng tên mô-đun (phổ biến).  
  2. # Chỉ sử dụng tên package để gọi flag trong code  
  3. từ absl nhập cờtừ doctor.who nhập jodie  
  4. CỜ = cờ.CỜ 

Không: (giả sử tệp nằm trong Doctor/who, jodie.py cũng ở đây).

  1. # Không rõ tác giả muốn mô-đun nào và mô-đun nào sẽ được nhập. Thực tế  
  2. # hành vi nhập phụ thuộc vào các yếu tố bên ngoài kiểm soát sys.path.  
  3. # Tác giả có ý định nhập mô-đun jodie nào? 
  4. # Không rõ tác giả muốn gói nào và gói nào cuối cùng được nhập.  
  5. # Hoạt động nhập thực tế phụ thuộc vào sys.path được kiểm soát bởi các tham số bên ngoài  
  6. # Vậy tác giả muốn nhập mô-đun jodie nào?  
  7. nhập khẩu jodie 

Không nên giả định rằng đường dẫn đến mã chính được bao gồm trong sys.path, ngay cả khi nó đôi khi hoạt động trong mã ví dụ trước, chúng ta nên nghĩ rằng import jodie đề cập đến việc nhập gói của bên thứ ba có tên jodie hoặc jodie vào. thư mục cấp cao nhất thay vì jodie.py trong đường dẫn hiện tại.

2.4 Ngoại lệ

Cho phép xử lý ngoại lệ nhưng phải thận trọng khi sử dụng.

2.4.1 Định nghĩa.

Các ngoại lệ là phương tiện thoát ra khỏi luồng điều khiển của đoạn mã thông thường để xử lý lỗi hoặc các điều kiện bất thường khác.

2.4.2 Ưu điểm 。

Luồng điều khiển của mã thông thường sẽ không bị ảnh hưởng bởi mã xử lý lỗi. Việc xử lý ngoại lệ cũng cho phép luồng điều khiển bỏ qua nhiều phần mã trong một số trường hợp, chẳng hạn như trả về kết quả từ N hàm nhúng ở một bước nhất định thay vì buộc phải tiếp tục lỗi. mã số. .

2.4.3 Nhược điểm 。

Nó có thể làm cho luồng điều khiển khó hiểu và có thể dễ bỏ sót lỗi hơn khi gọi các hàm thư viện.

2.4.4 Khuyến nghị.

Các trường hợp ngoại lệ phải tuân thủ các điều kiện cụ thể

  •  Sử dụng raise MyError('Error message') hoặc raise MyError(), không sử dụng 2 đoạn raise MyError, 'Error message'
  •  Khi lớp ngoại lệ tích hợp sẵn là hợp lý, hãy thử sử dụng các ngoại lệ tích hợp sẵn. Ví dụ: ném ValueError để chỉ ra rằng xảy ra lỗi chương trình vi phạm tiền đề đặt trước (chẳng hạn như chuyển số âm sang tình huống yêu cầu số dương). ).

Không sử dụng khẳng định để phân đoạn các giá trị tham số cấu trúc công khai. Khẳng định được sử dụng để xác nhận tính chính xác của các phép tính nội bộ và không được sử dụng để chỉ ra sự xuất hiện của một số sự kiện không mong muốn cho quá trình xử lý tiếp theo, hãy sử dụng câu lệnh nâng cao để xử lý nó. , chẳng hạn như

Đúng

  1. def connect_to_next_port(self, tối thiểu):  
  2. """Kết nối tới cổng khả dụng tiếp theo.  
  3. Lập luận:  
  4.     tối thiểu: Giá trị cổng lớn hơn hoặc bằng 1024.  
  5. Trả về:  
  6.     Cổng tối thiểu mới.  
  7. Tăng:  
  8.     ConnectionError: Nếu không tìm thấy cổng nào khả dụng.  
  9. """  
  10. nếu tối thiểu < 1024:  
  11.     # Lưu ý rằng việc tăng ValueError này không được đề cập trong tài liệu  
  12.     # phần "Raises:" của chuỗi vì nó không phù hợp để  
  13.     # đảm bảo phản ứng hành vi cụ thể này đối với việc sử dụng sai API.  
  14.     # Lưu ý rằng việc ném ValueError không được đề cập trong Raise trong chuỗi tài liệu, vì điều này không phù hợp để đảm bảo phản hồi đặc biệt về việc sử dụng sai API.  
  15.     raise ValueError('Cổng tối thiểu phải là ít nhất 1024, không phải %d.' % (tối thiểu,))  
  16. cảng = bản thân._find_next_open_port(tối thiểu)  
  17. nếu không phải là cổng:  
  18.     raise ConnectionError('Không thể kết nối tới dịch vụ trên %d hoặc cao hơn.' % (tối thiểu,))  
  19. khẳng định cổng >= tối thiểu, 'Cổng không mong muốn %d khi giá trị tối thiểu là %d.' % (cổng, tối thiểu)  
  20. cổng trả về 

KHÔNG

  1. def connect_to_next_port(self, tối thiểu):  
  2. """Kết nối tới cổng khả dụng tiếp theo.  
  3. Lập luận:  
  4.     tối thiểu: Giá trị cổng lớn hơn hoặc bằng 1024.  
  5. Trả về:  
  6.     Cổng tối thiểu mới.  
  7. """  
  8. khẳng định tối thiểu >= 1024, 'Cổng tối thiểu phải là 1024.'  
  9. cảng = bản thân._find_next_open_port(tối thiểu)  
  10. khẳng định cổng không phải là Không có  
  11. cổng trả về 
  •  Các thư viện hoặc gói có thể xác định các ngoại lệ của riêng chúng. Khi làm như vậy, chúng phải mở rộng một lớp ngoại lệ hiện có. Tên của lớp ngoại lệ phải kết thúc bằng Lỗi và không được trùng lặp (foo.FooError).
  •  Không bao giờ sử dụng câu lệnh ngoại trừ: để bắt tất cả các ngoại lệ hoặc bắt Ngoại lệ hoặc StandardError trừ khi:
  •  Python rất khoan dung với điều này và câu lệnh ngoại trừ: sẽ bắt lỗi chính tả, chấm dứt sys.exit(), Ctrl+C, lỗi kiểm tra đơn vị và tất cả các trường hợp ngoại lệ khác mà bạn có thể không mong đợi.
    •  Ném lại ngoại lệ này
    •  Tạo một điểm biệt lập trong chương trình nơi ngoại lệ sẽ không tiếp tục nhưng sẽ được ghi lại và loại bỏ (ví dụ: bằng cách bảo vệ lớp ngoài cùng để bảo vệ luồng khỏi bị lỗi).
  •  Giảm thiểu số lượng mã bên trong biểu thức thử/ngoại trừ Mã trong khối mã thử càng lớn thì càng có nhiều khả năng xảy ra ngoại lệ trong mã mà bạn không muốn ném. ngoại trừ Mặt nạ một sự bất thường thực sự
  •  Sử dụng cuối cùng để thực thi mã sẽ được thực thi bất kể ngoại lệ có được ném vào khối thử hay không. Điều này rất hữu ích khi dọn dẹp (tức là đóng tệp).
  •  Khi phát hiện ngoại lệ, hãy sử dụng as thay vì dấu phẩy để phân tách các phần. 
  1. thử:  
  2.     nâng cao Lỗi()  
  3. ngoại trừ Lỗi như lỗi:  
  4.     vượt qua 
2.5 Biến toàn cục

Tránh các biến toàn cục.

2.5.1 Định nghĩa.

Các biến được khai báo ở cấp mô-đun hoặc dưới dạng thuộc tính lớp.

2.5.2 Ưu điểm 。

Đôi khi hữu ích.

2.5.3 Nhược điểm 。

Trong quá trình nhập, có thể thay đổi hành vi của mô-đun vì các biến toàn cục đã được khai báo khi mô-đun được giới thiệu lần đầu tiên.

2.5.4 Khuyến nghị.

Tránh các biến toàn cục.

Là các biến kỹ thuật, các hằng số cấp mô-đun được phép và khuyến khích sử dụng. Ví dụ: MAX_HOLY_HANDGRENADE_COUNT = 3, các hằng số phải bao gồm chữ in hoa và dấu gạch dưới, hãy xem quy tắc đặt tên bên dưới.

Nếu cần, các biến toàn cục cần được khai báo ở cấp mô-đun và đặt ở chế độ riêng tư trong mô-đun bằng cách thêm _ vào trước tên biến. Quyền truy cập bên ngoài vào các biến toàn cục của mô-đun phải thông qua các hàm cấp mô-đun công khai, xem quy tắc đặt tên bên dưới.

2.6 Các lớp và hàm nhúng/cục bộ/bên trong

Các hàm hoặc lớp cục bộ nội tuyến vẫn ổn khi đóng các biến cục bộ. (Chú thích: Sự hiểu biết của tôi ở đây là ổn khi các hàm hoặc lớp cục bộ nội tuyến nằm trong cùng phạm vi đóng với các biến cục bộ. ).

2.6.1 Định nghĩa.

Các lớp có thể được định nghĩa trong các phương thức, hàm và các hàm có thể được định nghĩa trong các phương thức hoặc hàm lồng nhau có quyền truy cập chỉ đọc vào các biến của phạm vi kèm theo.

2.6.2 Ưu điểm 。

Cho phép định nghĩa các lớp tiện ích hoặc hàm tiện ích chỉ khả dụng trong phạm vi rất hạn chế. Rất ADT-y (??Tuân thủ các yêu cầu về kiểu dữ liệu trừu tượng???), thường được sử dụng để triển khai các trình trang trí.

2.6.3 Nhược điểm 。

Không thể chọn các thể hiện của lớp lồng nhau hoặc lớp cục bộ và không thể kiểm tra trực tiếp các hàm hoặc lớp lồng nhau Việc lồng nhau làm cho các hàm bên ngoài dài hơn và khó đọc hơn.

2.6.4 Khuyến nghị.

Ngoại trừ một số khai báo đặc biệt, các lớp và hàm nội tuyến/cục bộ/bên trong này đều ổn. Tránh các hàm hoặc lớp nội tuyến trừ khi bạn cần đóng một giá trị cục bộ (Người dịch hiểu rằng nó có thể bổ sung cho việc đặt các biến cục bộ trong cùng một giá trị. function. (ngoại trừ trường hợp miền). Không biến hàm thành lệnh nội tuyến để tránh truy cập. Trong trường hợp này, hãy đặt hàm ở cấp mô-đun và thêm _ vào tên hàm để đảm bảo rằng thử nghiệm có thể truy cập. chức năng.

2.7 Hiểu danh sách và biểu thức tạo

Có sẵn trong các trường hợp đơn giản.

2.7.1 Định nghĩa.

Các biểu thức trình tạo và tạo phái sinh List, Dict và Set cung cấp một cách ngắn gọn và hiệu quả để tạo các vùng chứa và trình vòng lặp mà không cần các vòng lặp, biểu thức map(), filter() hoặc lambda truyền thống.

2.7.2 Ưu điểm 。

Các biểu thức suy luận đơn giản sẽ ngắn gọn và rõ ràng hơn các phương pháp tạo từ điển, danh sách hoặc tập hợp khác có thể rất hiệu quả vì hoàn toàn tránh được việc tạo danh sách.

2.7.3 Nhược điểm 。

Các biểu thức phái sinh hoặc trình tạo được tải rất khó đọc.

2.7.4 Khuyến nghị.

Có thể sử dụng nó trong các trường hợp đơn giản. Mỗi phần (biểu thức ánh xạ, biểu thức lọc, v.v.) phải được hoàn thành trong một dòng. Không được phép sử dụng nhiều mệnh đề hoặc biểu thức lọc. một vòng lặp.

Đúng

  1. kết quả = [mapping_expr cho giá trị trong iterable nếu filter_expr]  
  2. kết quả = [{'key': value} cho giá trị trong iterable  
  3.           nếu a_long_filter_expression(giá trị)]  
  4. kết quả = [biến_đổi_phức_tạp(x)  
  5.           đối với x trong iterable nếu predicate(x)] 
  6. tên mô tả = [ 
  7.     biến đổi({'key': key, 'value': value}, màu sắc='đen' 
  8.     cho khóa, giá trị trong generate_iterable(some_input)  
  9.     nếu complicated_condition_is_met(key, value)  
  10. kết quả = []  
  11. đối với x trong phạm vi (10):  
  12.     đối với y trong phạm vi (5):  
  13.         nếu x * y > 10:  
  14.             result.append((x, y))  
  15. trả về {x: complicated_transform(x)  
  16.         cho x trong long_generator_function(tham số)  
  17.         nếu x không phải là None}  
  18. máy phát điện hình vuông = (x**2 cho x trong phạm vi(10))  
  19. tên_duy_nhất = {user.name cho người dùng trong users nếu người dùng không phải là None} 
  20. ăn(jelly_bean cho jelly_bean trong jelly_beans  
  21.     nếu như thạch_đậu.màu == 'đen') 

KHÔNG

  1. kết quả = [biến đổi phức tạp(  
  2.           x, một số_đối_số=x+1)  
  3.           đối với x trong iterable nếu predicate(x)]  
  4. kết quả = [(x, y) với x trong phạm vi (10) với y trong phạm vi (5) nếu x * y > 10]  
  5. trả về ((x, y, z)  
  6.         cho x trong phạm vi(5) 
  7.         cho y trong phạm vi(5)  
  8.         nếu x != y  
  9.         cho z trong phạm vi(5)  
  10.         nếu y != z) 
2.8 Các trình vòng lặp và toán tử mặc định

Sử dụng chúng cho các loại hỗ trợ trình vòng lặp mặc định và thuật toán đám mây như danh sách, từ điển và tệp.

2.8.1 Định nghĩa.

Các loại vùng chứa (chẳng hạn như từ điển, danh sách, v.v.) xác định các trình vòng lặp mặc định và toán tử kiểm tra thành viên.

Ưu điểm 。

Các trình vòng lặp và toán tử mặc định rất đơn giản và hiệu quả, đồng thời có thể biểu diễn các thao tác một cách trực tiếp mà không cần gọi các phương thức bổ sung. Các hàm sử dụng toán tử mặc định là phổ biến và có thể được sử dụng với bất kỳ loại nào hỗ trợ các thao tác này.

Nhược điểm .

Loại không thể được phân biệt bằng tên phương thức, ví dụ has_key() có nghĩa là từ điển, tất nhiên đây cũng là một lợi thế.

gợi ý.

Đối với các loại được hỗ trợ như danh sách, từ điển và tệp, hãy sử dụng các trình vòng lặp và toán tử mặc định. Các loại tích hợp cũng xác định các phương thức vòng lặp này. Sử dụng các phương thức này ưu tiên hơn các phương thức trả về danh sách. Sẽ thay đổi vùng chứa. Không sử dụng các phương pháp lặp độc quyền của Python 2 trừ khi cần thiết.

Đúng

  1. để khóa trong adict: ... 
  2. nếu khóa không nằm trong adict: ... 
  3. nếu obj trong alist: ...  
  4. cho dòng trong tệp: ...  
  5. đối với k, v trong adict.items(): ...  
  6. đối với k, v trong sáu.iteritems(adict): ... 

KHÔNG

  1. để khóa trong adict.keys(): ...  
  2. nếu không adict.has_key(key): ...  
  3. đối với dòng trong afile.readlines(): ...  
  4. đối với k, v trong dict.iteritems(): ... 
2.9 Máy phát điện

Sử dụng máy phát điện khi cần thiết.

2.9.1 Định nghĩa.

Hàm tạo trả về một trình vòng lặp tạo ra một giá trị mỗi khi câu lệnh lợi suất được thực thi. Sau khi tạo một giá trị, việc thực thi hàm tạo sẽ bị tạm dừng cho đến khi cần giá trị tiếp theo.

2.9.2 Ưu điểm 。

Đơn giản hóa mã, vì các biến cục bộ và luồng điều khiển được giữ nguyên trong mỗi lệnh gọi, nên trình tạo sẽ tiết kiệm bộ nhớ hơn so với việc tạo toàn bộ danh sách giá trị cùng một lúc.

2.9.3 Nhược điểm 。

không có.

2.9.4 Khuyến nghị.

Bạn nên sử dụng "Lợi nhuận:" thay vì "Trả về:" trong chuỗi tài liệu của hàm tạo.

2.10 Biểu thức Lambda

Điều này tốt cho một dòng mã.

2.10.1 Định nghĩa.

Lambda xác định hàm ẩn danh trong một biểu thức chứ không phải trong câu lệnh. Biểu thức Lambda thường được sử dụng để xác định các hàm gọi lại hoặc toán tử được sử dụng bởi các hàm bậc cao hơn (chẳng hạn như map() và filter()).

2.10.2 Ưu điểm 。

thuận lợi.

2.10.3 Nhược điểm 。

Khó đọc và gỡ lỗi hơn các hàm cục bộ, tính ẩn danh có nghĩa là dấu vết ngăn xếp khó hiểu hơn vì tính biểu cảm bị hạn chế vì các hàm lambda chỉ chứa một biểu thức.

2.10.4 Khuyến nghị.

Đối với một dòng mã, bạn có thể sử dụng biểu thức lambda. Nếu mã trong biểu thức lambda vượt quá 60-80 ký tự, tốt nhất bạn nên xác định mã đó là hàm nội tuyến thông thường.

Đối với các thao tác chung như phép nhân, hãy sử dụng các hàm dựng sẵn của mô-đun toán tử thay vì xác định lại các hàm ẩn danh, ví dụ: sử dụng operator.mul thay vì lambda x,y: x * y.

2.11 Biểu thức điều kiện

Có thể sử dụng trong những trường hợp đơn giản.

2.11.1 Định nghĩa.

Biểu thức điều kiện (còn được gọi là toán tử bậc ba) là một thay thế ngắn hơn cho câu lệnh if. Ví dụ: x = 1 if cond else 2 .

2.11.2 Ưu điểm 。

Nó ngắn hơn và thuận tiện hơn câu lệnh if.

2.11.3 Nhược điểm 。

Nó có thể khó đọc hơn câu lệnh if và phần điều kiện có thể khó xác định khi biểu thức dài.

2.11.4 Khuyến nghị.

Có thể được sử dụng trong các trường hợp đơn giản. Mỗi phần (biểu thức đúng, biểu thức if, biểu thức khác) phải được hoàn thành trong một dòng. Nếu biểu thức điều kiện rất phong phú, hãy sử dụng câu lệnh if hoàn chỉnh.

Đúng

  1. một_dòng = 'Đúng' nếu vị ngữ(giá trị) thì 'không'  
  2. hơi tách ra = ('có' nếu vị ngữ(giá trị) 
  3.                   ngược lại 'không, không, rất thích')  
  4. phong cách ba ngôi dài nhất có thể thực hiện được = (  
  5.     'vâng, đúng, khẳng định, xác nhận, chính xác'  
  6.     nếu vị ngữ(giá trị)  
  7.     nếu không thì 'không, sai, phủ định, không') 

KHÔNG

  1. phá vỡ dòng xấu = ('có' nếu vị ngữ(giá trị) khác  
  2.                      'KHÔNG')phần_quá_dài = ('có'  
  3.                     nếu some_long_module.some_long_predicate_function(  
  4.                         tên_biến_thực_sự_dài)  
  5.                     nếu không thì 'không, sai, phủ định, không') 
2.12 Giá trị tham số mặc định

Được trong hầu hết các trường hợp.

2.12.1 Định nghĩa.

Giá trị của biến có thể được đặt ở cuối danh sách tham số hàm, ví dụ def foo(a, b=0):. Nếu foo chỉ truyền vào một tham số khi gọi thì biến b sẽ được đặt thành 0. Nếu foo được gọi, biến b sẽ được đặt thành 0. Nhập hai tham số, sau đó b được gán giá trị tham số thứ hai.

2.12.2 Ưu điểm 。

Thông thường, một hàm có thể có số lượng lớn các giá trị mặc định, nhưng hiếm khi cần sửa đổi các giá trị mặc định này. Các giá trị mặc định này cung cấp một cách đơn giản để đáp ứng các tình huống trên mà không cần phải xác định lại nhiều hàm cho các tình huống hiếm gặp này. không hỗ trợ các phương thức hoặc hàm nạp chồng, các tham số mặc định là một cách dễ dàng để thực hiện hành vi "giả quá tải".

2.12.3 Nhược điểm 。

Các tham số mặc định được sao chép khi mô-đun được tải. Điều này gây ra sự cố khi tham số là các đối tượng có thể thay đổi (chẳng hạn như danh sách hoặc từ điển). được thay đổi..

2.12.4 Khuyến nghị.

Vui lòng lưu ý cảnh báo sau khi sử dụng - không sử dụng các đối tượng có thể thay đổi làm giá trị mặc định khi xác định hàm hoặc phương thức.

Đúng

  1. đặt ở đó(a, b=Không có):  
  2.     nếu b là Không:  
  3.         b = []  
  4. def foo(a, b: Tùy chọn[Trình tự] = Không có):  
  5.     nếu b là Không:  
  6.         b = []  
  7. đặt ở đâu (a, b: Sự liên tiếp = ()): # Bộ dữ liệu trống OK vì bộ dữ liệu là bất biến Bộ dữ liệu trống cũng không thể thay đổi  
  8.     ... 

KHÔNG

  1. đặt ở đó(a, b=[]):  
  2.     ...  
  3. đặt ở đó(a, b=thời gian.time()): # Thời gian nạp module???  
  4.     ... 
  5. đặt ở đó(a, b=CỜ.my_thing): # sys.argv chưa được phân tích cú pháp... sys.argv chưa được phân tích cú pháp...  
  6.     ...  
  7. đặt ở đâu (a, b: Bản đồ = {}): # Vẫn có thể được chuyển sang mã không được kiểm tra Mã không được kiểm tra vẫn có thể được chuyển vào (bản dịch ở đây có thể sai)  
  8.     ... 
2.13 Thuộc tính

Sử dụng các thuộc tính để truy cập hoặc thiết lập dữ liệu thông qua các phương thức truy cập và setter đơn giản và nhẹ.

2.13.1 Định nghĩa.

Lệnh gọi trang trí như một cách để lấy và đặt một thuộc tính làm quyền truy cập thuộc tính tiêu chuẩn trong khi việc tính toán diễn ra nhẹ nhàng.

2.13.2 Ưu điểm 。

Để truy cập thuộc tính đơn giản, việc giảm các phương thức get và set rõ ràng có thể cải thiện khả năng đọc. Cho phép đánh giá lười biếng. Đây được coi là một cách Pythonic để duy trì các giao diện lớp. Về mặt hiệu suất, việc truy cập trực tiếp vào các biến là hợp lý hơn, cho phép các thuộc tính bỏ qua các yêu cầu. các phương pháp truy cập tầm thường.

2.13.3 Nhược điểm 。

Trong Python 2, bạn phải kế thừa từ đối tượng, điều này có thể ẩn các tác dụng phụ như nạp chồng toán tử Đối với các lớp con, các thuộc tính có thể hơi khó hiểu.

2.13.4 Khuyến nghị.

Các thuộc tính được sử dụng để truy cập hoặc đặt dữ liệu trong mã mới thường có các phương thức thiết lập và truy cập đơn giản và nhẹ. Các thuộc tính được trang trí bằng @property khi chúng được tạo, thêm trình trang trí.

Nếu bản thân thuộc tính không bị ghi đè, thì việc kế thừa thuộc tính có thể không đủ rõ ràng và bạn phải đảm bảo rằng phương thức truy cập được truy cập gián tiếp để đảm bảo rằng quá tải phương thức của lớp con được gọi bởi thuộc tính (sử dụng Phương thức mẫu DP, người dịch: Nên là mẫu thiết kế phương thức mẫu).

Đúng

  1. lớp Square(đối tượng): 
  2.     """Một hình vuông có hai thuộc tính: vùng có thể ghi và chu vi chỉ đọc.  
  3.     Để sử dụng:  
  4.     >>> vuông = Quảng trường(3) 
  5.     >>> diện tích vuông  
  6.     9  
  7.     >>> chu vi vuông  
  8.     12  
  9.     >>> diện tích vuông = 16  
  10.     >>> cạnh vuông  
  11.     4  
  12.     >>> chu vi vuông  
  13.     16  
  14.     """  
  15.     def __init__(bản thân, bên):  
  16.         tự.bên = bên  
  17.     @tài sản  
  18.     def area(self):  
  19.         """Diện tích hình vuông."""  
  20.         trả về self._get_area()  
  21.     @khu vực.setter  
  22.     def area(self, area):  
  23.         trả về self._set_area(khu vực)  
  24.     def _get_area(bản thân): 
  25.         """Trình truy cập gián tiếp để tính toán thuộc tính 'diện tích'."""  
  26.         trả về self.side ** 2  
  27.     def _set_area(bản thân, diện tích): 
  28.         """Bộ thiết lập gián tiếp để thiết lập thuộc tính 'khu vực'."""  
  29.         tự.bên = toán học.sqrt(diện tích) 
  30.     @tài sản 
  31.     def chu vi(self):  
  32.         trả về self.side * 4 
2.14 Biểu thức Đúng/Sai

Bất cứ khi nào có thể, hãy sử dụng câu lệnh if có hàm ý Sai.

2.14.1 Định nghĩa.

Trong môi trường Boolean, Python xác định các giá trị nhất định là Sai. Một nguyên tắc nhỏ là tất cả các giá trị "null" đều được coi là Sai, vì vậy các giá trị Boolean là 0, Không có, [], {}, '' đều là Sai.

2.14.2 Ưu điểm 。

Các câu lệnh có điều kiện sử dụng kiểu boolean của Python dễ đọc hơn và khó mắc lỗi hơn và trong hầu hết các trường hợp, chúng cũng nhanh hơn.

2.14.3 Nhược điểm 。

Điều này có vẻ lạ đối với các nhà phát triển C/C++.

gợi ý.

Nếu có thể, hãy sử dụng Sai ẩn. Ví dụ: sử dụng if foo: thay vì if foo != []: Dưới đây là một số lưu ý bạn nên ghi nhớ:

  •  Sử dụng nếu foo là Không (hoặc nếu foo không phải là Không) để kiểm tra Không. Ví dụ: khi kiểm tra xem một biến hoặc tham số có giá trị mặc định là Không có đã được gán một giá trị khác hay chưa, giá trị Boolean của giá trị khác được chỉ định có thể là Sai. .
  •  Không sử dụng == để so sánh một biến có giá trị Boolean là Sai. Nếu bạn cần phân biệt giữa Sai và Không, hãy sử dụng biểu thức chuỗi chẳng hạn như if not x và x is not None.
  •  Đối với các chuỗi (chẳng hạn như chuỗi, danh sách, bộ dữ liệu), hãy tận dụng thực tế là chuỗi trống là Sai, vì vậy hãy sử dụng if seq: và if not seq: tương ứng thay vì if len(seq) hoặc if not len(seq): .
  •  Khi xử lý số nguyên, Sai ngầm định có thể gây ra nhiều rủi ro hơn (chẳng hạn như vô tình xử lý Không và 0 theo cùng một cách). Bạn có thể sử dụng một giá trị đã biết là số nguyên (chứ không phải kết quả của len()) và số nguyên. 0 so sánh.

Đúng

  1. nếu không phải người dùng:  
  2.     in('không có người dùng')  
  3. nếu như đồ ăn == 0: 
  4.     self.handle_zero()  
  5. nếu tôi % 10 == 0:  
  6.     self.handle_multiple_of_ten()  
  7. định nghĩa f(x=Không có):  
  8.     nếu x là Không có:  
  9.         x = [] 

KHÔNG

  1. nếu len(users) == 0: 
  2.     in('không có người dùng') 
  3. nếu foo không phải là None và không phải foo:  
  4.     self.handle_zero() 
  5. nếu không thì % 10:  
  6.     self.handle_multiple_of_ten()  
  7. định nghĩa f(x=Không có):  
  8.     xx = x hoặc [] 
2.15 Tính năng ngôn ngữ không được dùng nữa

Sử dụng các phương thức chuỗi thay vì mô-đun chuỗi bất cứ khi nào có thể. Sử dụng cú pháp gọi hàm thay vì áp dụng. Khi tham số hàm là một hàm ẩn danh nội tuyến, hãy sử dụng các biểu thức hiểu danh sách và vòng lặp for thay vì các bộ lọc và bản đồ.

2.15.1 Định nghĩa.

Phiên bản hiện tại của Python cung cấp một cách xây dựng thường được ưa chuộng hơn... .

2.15.2 Khuyến nghị.

Chúng tôi không sử dụng bất kỳ phiên bản Python nào không hỗ trợ các tính năng này, vì vậy không có lý do gì để không sử dụng cách mới.

Đúng

  1. từ = đồ ăn.tách ra(':')  
  2. [x[1] cho x trong my_list nếu x[2] == 5]  
  3. map(math.sqrt, data) # Ok. Không có biểu thức lambda nội tuyến. Có, không có biểu thức lambda nội tuyến.  
  4. fn(*đối số, **kwargs) 

KHÔNG

  1. từ = sợi dây.split(foo, ':')  
  2. bản đồ(lambda x: x[1], bộ lọc(lambda x: x[2] == 5, my_list))  
  3. áp dụng(fn, args, kwargs) 
2.16 Phạm vi từ vựng

Có thể được sử dụng.

2.16.1 Định nghĩa.

Hàm Python nội tuyến có thể tham chiếu các biến được xác định trong không gian tên đóng, nhưng không thể sao chép chúng. Các liên kết biến được giải quyết bằng phạm vi từ vựng, tức là dựa trên văn bản chương trình tĩnh. các biến cục bộ, ngay cả khi được sử dụng trước khi gán. Nếu có khai báo toàn cục, tên sẽ được coi là biến toàn cục.

Một ví dụ về việc sử dụng tính năng này là

  1. chắc chắn get_adder(summand1):  
  2.     """Trả về một hàm cộng các số vào một số đã cho."""  
  3.     bộ cộng def(summand2):  
  4.         trả về tổng lệnh1 + tổng lệnh2  
  5.     trả về bộ cộng 

2.16.2 Ưu điểm 。

Nó thường làm cho mã ngắn gọn và trang nhã hơn, đặc biệt đối với các chương trình Lisp và Lược đồ (cũng như Haskell và ML và các chương trình khác) có kinh nghiệm.

2.16.3 Nhược điểm 。

Có thể dẫn đến các lỗi khó hiểu như ví dụ này dựa trên PEP-0227.

  1. Tôi = 4  
  2. đặt foo(x): 
  3.     thanh def(): 
  4.         in(tôi, kết thúc=''
  5.     # ...  
  6.     # Một số mã ở đây 
  7.     # ...  
  8.     for i in x: # Ah, i *is* cục bộ của foo, vì vậy đây là những gì bar thấy i là một biến cục bộ cho foo, vì vậy đây là giá trị mà hàm bar thu được 
  9.         in(tôi, kết thúc=''
  10.     thanh() 

Vì vậy foo([1, 2, 3]) sẽ in 1 2 3 3 thay vì 1 2 3 4. .

2.16.4 Khuyến nghị.

Có thể được sử dụng.

2.17 Trang trí hàm và phương thức

Khi có lợi ích rõ ràng, hãy sử dụng nó một cách khôn ngoan, tránh @staticmethod và sử dụng @classmethod một cách tiết kiệm.

2.17.1 Định nghĩa.

Trình trang trí hàm và phương thức (nghĩa là dấu @). Một trình trang trí phổ biến là @property, được sử dụng để chuyển đổi các phương thức thông thường thành các thuộc tính được tính toán động. Tuy nhiên, cú pháp trang trí cũng cho phép người dùng xác định các trình trang trí, đặc biệt đối với một số hàm my_trang trí. như sau

  1. lớp C(đối tượng):  
  2.     @my_decorator  
  3.     def phương thức(self):  
  4.         # thân phương thức ... 

tương đương với .

  1. lớp C(đối tượng):  
  2.     def phương thức(self):  
  3.         # thân phương thức ...  
  4.     phương pháp = người trang trí của tôi(phương pháp) 

2.17.2 Ưu điểm 。

Có thể thực hiện một số phép biến đổi nhất định trên các phương thức một cách duyên dáng, điều này có thể làm giảm một số mã lặp đi lặp lại và duy trì tính bất biến, v.v.

2.17.3 Nhược điểm 。

Trình trang trí có thể hoạt động tùy ý trên các tham số và giá trị trả về của hàm, dẫn đến hành vi hoạt động rất vô hình. Ngoài ra, trình trang trí được thực thi khi được nhập và hiệu quả của mã trang trí có thể rất khó khôi phục.

2.17.4 Khuyến nghị.

Sử dụng trang trí một cách tiết kiệm khi có lợi ích rõ ràng. Trình trang trí phải tuân theo các nguyên tắc nhập và đặt tên giống như các hàm. Tài liệu dành cho trình trang trí phải khai báo rõ ràng rằng hàm đó là một hàm trang trí. Và các bài kiểm tra đơn vị phải được viết cho các hàm trang trí.

Tránh các phần phụ thuộc bên ngoài của chính trình trang trí (chẳng hạn như không dựa vào tệp, ổ cắm, kết nối cơ sở dữ liệu, v.v.). Điều này là do các phần phụ thuộc bên ngoài này có thể xảy ra khi trình trang trí đang chạy (khi nhập, có thể từ pydoc hoặc các công cụ khác). . Trình trang trí được gọi với các đối số hợp lệ phải được đảm bảo khả dụng (càng nhiều càng tốt) trong mọi trường hợp.

Trình trang trí là một loại "mã cấp cao nhất" đặc biệt, xem main.

Không bao giờ sử dụng @staticmethod trừ khi bạn phải tích hợp API vào thư viện hiện có và thay vào đó viết hàm cấp mô-đun.

Chỉ sử dụng @classmethod khi viết một hàm tạo có tên hoặc một quy trình dành riêng cho lớp để sửa đổi trạng thái chung cần thiết (chẳng hạn như bộ đệm quy trình, v.v.).

2.18 Chủ đề

Đừng dựa vào tính nguyên tử của các loại tích hợp.

Mặc dù các kiểu dữ liệu cài sẵn của Python như từ điển dường như có các hoạt động nguyên tử, nhưng có một số trường hợp hiếm hoi trong đó chúng không phải là nguyên tử (ví dụ: nếu __hash__ hoặc __eq__ được triển khai như các phương thức Python) và bạn không nên dựa vào các kiểu này . Tính nguyên tử cũng không nên dựa vào phép gán biến nguyên tử (vì điều này phụ thuộc vào từ điển).

Ưu tiên sử dụng lớp Queue của mô-đun Queue như một cách để giao tiếp dữ liệu giữa các luồng. Ngoài ra, nếu bạn sử dụng mô-đun luồng và các nguyên hàm khóa của nó (khóa nguyên thủy), hãy hiểu cách sử dụng hợp lý các biến điều kiện để có thể sử dụng luồng. Điều kiện thay vì sử dụng những cái cấp thấp hơn.

2.19 Tính năng quá mạnh mẽ

Cố gắng tránh sử dụng nó.

2.19.1 Định nghĩa.

Python là một ngôn ngữ rất linh hoạt và cung cấp nhiều tính năng mới, chẳng hạn như siêu dữ liệu tùy chỉnh, truy cập mã byte, biên dịch động, kế thừa động, xác định lại lớp cha đối tượng, hack nhập, phản chiếu (chẳng hạn như một số cho ứng dụng getattr()), hệ thống được xây dựng- trong các sửa đổi, v.v.

2.19.2 Ưu điểm 。

Đây là những tính năng ngôn ngữ rất mạnh mẽ có thể làm cho chương trình trở nên nhỏ gọn hơn.

2.19.3 Nhược điểm 。

Thật hấp dẫn khi sử dụng các tính năng mới này, nhưng nó không thực sự cần thiết. Chúng khó đọc và khó hiểu. Việc gỡ lỗi mã sử dụng các tính năng khác thường có thể không đúng với tác giả ban đầu, nhưng khi bạn. nhìn lại mã, nó có thể khó hơn mã dài hơn nhưng trực tiếp hơn ...

2.19.4 Định nghĩa.

Tránh sử dụng các tính năng này trong mã của bạn.

Các thư viện và lớp tiêu chuẩn sử dụng các tính năng này trong nội bộ đều có sẵn (chẳng hạn như abc.ABCMeta, Collection.namedtuple và enum).

2.20 Phiên bản mới của Python: Python3 và __future__import

Python 3 đã có sẵn (Trình dịch: Python 2 hiện không còn được hỗ trợ) và mặc dù không phải mọi dự án đều sẵn sàng sử dụng Python 3, nhưng tất cả mã phải tương thích với Python 3 và được thử nghiệm trong môi trường Python 3 nếu có thể.

2.20.1 Định nghĩa.

Python 3 là một thay đổi lớn đối với Python. Mặc dù mã hiện tại thường được viết bằng Python 2.7, nhưng có một số điều đơn giản có thể được thực hiện để làm cho mã rõ ràng hơn về mục đích của nó, điều này có thể giúp mã chạy tốt hơn trong Python 3 mà không cần điều chỉnh. ..

2.20.2 Ưu điểm 。

Mã được viết bằng Python 3 sẽ rõ ràng hơn và dễ chạy hơn trong môi trường Python 3 khi đã có tất cả các phần phụ thuộc.

2.20.3 Nhược điểm 。

Một số người có thể nghĩ rằng bản soạn sẵn mặc định hơi xấu và việc nhập các tính năng không thực sự cần thiết vào một mô-đun là điều bất thường.

2.20.4 Khuyến nghị.

từ việc nhập khẩu trong tương lai 。

Việc sử dụng câu lệnh nhập từ __future__ được khuyến khích. Tất cả mã mới phải chứa mã bên dưới, trong khi mã hiện tại phải được cập nhật để tương thích nhất có thể.

  1. từ __future__ nhập absolute_import  
  2. từ __future__ nhập khẩu phân chia 
  3. từ __future__ nhập print_function 

Nếu bạn không quen với những điều này, hãy đọc chi tiết: nhập tuyệt đối, hành vi chia/mới và chức năng in.

Không bỏ qua hoặc loại bỏ các mục nhập này, ngay cả khi chúng không được sử dụng trong mô-đun, trừ khi mã chỉ được sử dụng trong Python3. Tốt nhất là luôn có các mục nhập từ tương lai trong tất cả các tài liệu để đảm bảo rằng không ai sẽ sử dụng nó sau này. trong khi chỉnh sửa...

Có các câu lệnh __future__import khác, hãy sử dụng chúng theo sở thích của bạn. Đề xuất của chúng tôi không bao gồm unicode_literals vì chúng không có lợi thế rõ ràng. Điều này là do chuyển đổi mã hóa mặc định ngầm đã được giới thiệu ở nhiều nơi trong Python 2.7. Hầu hết mã được trình bày rõ ràng nhất bằng cách sử dụng b'' và u'' btyes và chuỗi unicode (Người dịch: Bản dịch này có thể không chính xác).

Sáu thư viện tương lai hoặc quá khứ 。

Khi dự án cần hỗ trợ Python2 và 3, hãy sử dụng sáu, tương lai và quá khứ theo yêu cầu.

2.21 Mã có chú thích kiểu

Bạn có thể nhập chú thích mã Python3 theo PEP-484 và sử dụng các công cụ kiểm tra loại như pytype để thực hiện kiểm tra loại tại thời điểm xây dựng.

Loại nhận xét có thể ở dạng mã nguồn hoặc trong tệp pyi sơ khai. Bất cứ khi nào có thể, nhận xét phải được viết bằng mã nguồn. Đối với các mô-đun mở rộng hoặc của bên thứ ba, hãy sử dụng tệp pyi.

2.21.1 Định nghĩa.

Chú thích kiểu (còn được gọi là "gợi ý kiểu") được sử dụng cho các tham số hàm hoặc phương thức và giá trị trả về

  1. def func(a: int) -> Danh sách[int]: 

Bạn cũng có thể khai báo loại biến bằng chú thích riêng

  1. Một = Một số chức năng() # loại: SomeType 

2.21.2 Ưu điểm 。

Chú thích loại cải thiện khả năng đọc và khả năng bảo trì của mã. Việc kiểm tra loại sẽ chuyển nhiều lỗi thời gian chạy thành lỗi xây dựng và giảm khả năng sử dụng các tính năng quá mạnh.

2.21.3 Nhược điểm 。

Khai báo kiểu cần phải được cập nhật liên tục và lỗi kiểu có thể được báo cáo đối với mã được coi là hợp lệ. Việc sử dụng tính năng kiểm tra kiểu có thể làm giảm khả năng sử dụng các tính năng quá mạnh.

2.21.4 Khuyến nghị.

Phân tích loại Python được đặc biệt khuyến khích khi cập nhật mã. Khi thực hiện bổ sung và sửa đổi API công khai, hãy bao gồm các khai báo loại python và kiểm tra chúng thông qua pytype trong hệ thống xây dựng. các hiệu ứng (chẳng hạn như các loại được suy ra không chính xác) có thể từ chối sử dụng trong một số dự án như vậy, tác giả được khuyến khích thêm một liên kết thích hợp vào tệp BUILD kèm theo TODO hoặc một liên kết đến mô tả lỗi cho chú thích loại hiện chưa có. được bao gồm trong tìm kiếm.

3. Đặc tả kiểu mã Python

  。

3.1 dấu chấm phẩy

Không thêm dấu chấm phẩy vào cuối dòng hoặc sử dụng dấu chấm phẩy để kết hợp hai dòng câu lệnh thành một.

3.2 Chiều dài đường dây

Độ dài dòng tối đa là 80 ký tự.

Ngoại lệ rõ ràng vượt quá 80 ký tự

  •  nhập khẩu lâu
  •  Trong nhận xét: URL, đường dẫn, cờ, v.v.
  •  Các hằng chuỗi dài cấp mô-đun không chứa dấu cách và không thuận tiện khi ngắt dòng
  •  Sử dụng chú thích có thể đọc được của pylint (chẳng hạn như #pylint: vô hiệu hóa=tên không hợp lệ)

Không sử dụng nối dấu gạch chéo ngược ngoại trừ các trình quản lý bối cảnh yêu cầu ba cấp độ with trở lên.

Sử dụng nối dòng ngầm của Python bên trong dấu ngoặc đơn, dấu ngoặc và dấu ngoặc nhọn (phương thức nối dòng ngầm - kết nối khung, bao gồm (), [], {}). Nếu cần, bạn cũng có thể thêm một cặp dấu ngoặc bổ sung bên ngoài biểu thức.

Đúng

  1. foo_bar(self, chiều rộng, chiều cao, màu sắc='đen'thiết kế=Không cóx='đồ ngốc' 
  2.         sự nhấn mạnh=Không cóđiểm nổi bật=0 
  3. nếu như (chiều rộng == 0 và chiều cao == 0 và  
  4.     màu sắc == 'đỏ' và sự nhấn mạnh == 'mạnh'): 

Sử dụng dấu ngoặc đơn để nối các dòng ngầm khi một chuỗi không thể hoàn thành trong một dòng

  1. x = ('Điều này sẽ xây dựng một cái rất dài'  
  2.      'chuỗi dài dài dài dài dài dài') 

Trong phần nhận xét, hãy đặt các URL dài trên dòng riêng nếu cần

Đúng

  1. # Xem chi tiết tại  
  2. # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specuation.html 

KHÔNG

  1. # Xem chi tiết tại  
  2. # http://www.example.com/us/developer/documentation/api/content/\ 
  3. # v2.0/csv_file_name_extension_full_specification.html 

Khi xác định một biểu thức kéo dài từ ba dòng trở lên bằng câu lệnh with, bạn có thể sử dụng dấu gạch chéo ngược để phân tách các dòng. Đối với các biểu thức hai dòng, hãy sử dụng các câu lệnh lồng nhau.

Đúng

  1. với very_long_first_expression_function() là thư rác, \  
  2.      very_long_second_expression_function() như bean, \  
  3.      third_thing() dưới dạng trứng:  
  4.     place_order(trứng, đậu, spam, đậu) 
  5. với very_long_first_expression_function() là thư rác:  
  6.     với very_long_second_expression_function() làm bean:  
  7.         place_order(đậu, thư rác) 

KHÔNG

  1. với VeryLongFirstExpressionFunction() là thư rác, \  
  2.      VeryLongSecondExpressionFunction() dưới dạng bean:  
  3.     Đặt hàng (trứng, đậu, thịt hộp, đậu) 

Hãy chú ý đến thụt lề trong ví dụ trên, xem Thụt lề để biết chi tiết.

Trong các trường hợp khác, một dòng vượt quá 80 ký tự và công cụ định dạng tự động yapf không thể làm cho dòng nhánh đáp ứng yêu cầu thì được phép vượt quá giới hạn 80 ký tự.

3.3 Dấu ngoặc

Sử dụng dấu ngoặc đơn một cách thích hợp.

Mặc dù không cần thiết nhưng có thể sử dụng dấu ngoặc đơn xung quanh các bộ dữ liệu. Không sử dụng dấu ngoặc đơn trong câu lệnh trả về hoặc câu lệnh điều kiện trừ khi chúng được sử dụng để ngầm nối các hàng hoặc biểu thị các bộ dữ liệu.

Đúng

  1. nếu foo:  
  2.     thanh()  
  3. trong khi x:  
  4.     x = thanh()  
  5. nếu x và y:  
  6.     thanh()  
  7. nếu không x:  
  8.     thanh()  
  9. # Đối với một bộ 1 phần tử, dấu () dễ nhận biết hơn dấu phẩy.  
  10. bộ đồ liền thân = (đồ ngốc,) 
  11. trả lại foo  
  12. trả lại thư rác, đậu  
  13. trả về (thư rác, đậu)  
  14. đối với (x, y) trong dict.items(): ... 

KHÔNG

  1. nếu (x):  
  2.     thanh()  
  3. nếu không(x):  
  4.     thanh()  
  5. trả về (foo) 
3.4 Thụt lề

Sử dụng 4 dấu cách để thụt lề.

Không sử dụng các tab hoặc trộn các tab và dấu cách để thụt lề các phần mã. Nếu nhiều dòng được kết nối, các dòng phải được căn chỉnh theo chiều dọc hoặc thụt lề lại bằng 4 dấu cách (trong trường hợp này, dòng đầu tiên không được chứa mã sau dấu ngoặc). ).

Đúng

  1. # Căn chỉnh với dấu phân cách mở 
  2. # Căn chỉnh với dấu phân cách mở (người dịch hiểu là điểm vào của dấu phân cách, chẳng hạn như ba loại dấu ngoặc, dấu ngoặc chuỗi, v.v.)  
  3. đồ ăn = tên_hàm_dài(var_one, var_two,  
  4.                          var_ba, var_four)  
  5. bữa ăn = (thư rác, 
  6.         đậu)  
  7. # Căn chỉnh với dấu phân cách mở trong từ điển  
  8. đồ ăn = {  
  9.     long_dictionary_key: giá trị1 +  
  10.                          giá trị2,  
  11.     ...  
  12.  
  13. # Thụt lề 4 khoảng trắng; không có gì ở dòng đầu tiên  
  14. # Thụt lề 4 dấu cách, sau dấu ngoặc ở dòng đầu tiên không có nội dung 
  15. đồ ăn = tên_hàm_dài 
  16.     var_một, var_hai, var_ba,  
  17.     var_four)  
  18. bữa ăn = (  
  19.     thư rác, 
  20.     đậu)  
  21. # Thụt lề treo 4 khoảng trắng trong từ điển  
  22. đồ ăn = {  
  23.     khóa_từ_điển_dài:  
  24.         giá trị từ điển dài,  
  25.     ...  

KHÔNG

  1. # Nội dung trên dòng đầu tiên bị cấm 
  2. # Không được phép có nội dung ở dòng đầu tiên  
  3. đồ ăn = tên_hàm_dài(var_one, var_two,  
  4.     var_ba, var_four)  
  5. bữa ăn = (thư rác,  
  6.     đậu)  
  7. # 2-khoảng cách thụt lề bị cấm 
  8. đồ ăn = tên_hàm_dài 
  9.   var_một, var_hai, var_ba,  
  10.   var_four)  
  11. # Không có thụt lề treo trong từ điển 
  12. đồ ăn = {  
  13.     khóa_từ_điển_dài:  
  14.     giá trị từ điển dài,  
  15.     ...  

3.4.1 Về dấu phẩy ở cuối.

Về dấu phẩy ở cuối trong một chuỗi các phần tử, chỉ nên sử dụng nó khi các ký hiệu kết thúc vùng chứa ],) hoặc } không nằm trên cùng một dòng với phần tử cuối cùng. Sự hiện diện của dấu phẩy ở cuối cũng được sử dụng làm dấu nhắc. bằng công cụ định dạng tự động mã Python yapf của chúng tôi, tự động điều chỉnh các phần tử vùng chứa thành một phần tử trên mỗi hàng khi chúng xuất hiện sau phần tử cuối cùng.

Đúng

  1. golomb3 = [0, 1, 3] 
  2. golomb4 = [ 
  3.     0,  
  4.     1,  
  5.     4,  
  6.     6,  

KHÔNG

  1. golomb4 = [  
  2.     0,  
  3.     1,  
  4.     4,  
  5.     6  
3.5 Dòng trống

Cần có hai dòng giữa các định nghĩa cấp cao nhất (hàm hoặc lớp). Cần có một dòng trống giữa các định nghĩa phương thức và giữa dòng lớp và phương thức đầu tiên. Không được có dòng trống sau dòng def. thích hợp trong hàm hoặc phương thức Khi có thể sử dụng một dòng trống... .

3,6 khoảng trống

Thực hiện theo các quy tắc định dạng tiêu chuẩn về khoảng cách và dấu câu.

Không được có khoảng trắng thừa bên trong dấu ngoặc (), [], {}.

Đúng

  1. spam(ham[1], {trứng: 2}, []) 

KHÔNG

  1. spam( ham[ 1 ], { trứng: 2 }, [ ] ) 

Không được có khoảng trắng trước dấu phẩy, dấu chấm phẩy và dấu hai chấm nhưng phải thêm dấu cách sau chúng, trừ khi chúng ở cuối dòng.

Đúng

  1. nếu như x == 4:  
  2.     in(x, y) 
  3. x,  =y,x 

KHÔNG

  1. nếu như x == 4 :  
  2.     in(x, y)  
  3. x,  = y, x 

Trước dấu ngoặc đơn của lệnh gọi hàm, không có khoảng trắng nào trước dấu ngoặc đơn lát chỉ mục.

Đúng

  1. thư rác(1)  
  2. dict['key'] = danh sách[chỉ mục] 

KHÔNG

  1. thư rác (1)  
  2. dict ['key'] = danh sách [chỉ mục] 

Không thêm dấu cách ở cuối dòng.

Thêm trước và sau phép gán (=), so sánh (==,<,>,!=,<>,<=,>=,in,not in,is,is not) và các ký hiệu Boolean (và,hoặc,không ) Dấu cách. Thêm dấu cách trước và sau các toán tử số học (+,-,*,/,//,%,**,@) nếu thích hợp.

Đúng

  1. x == 1 

KHÔNG

  1. x<1 

Không thêm dấu cách trước và sau = khi truyền tham số tên từ khóa hoặc xác định giá trị tham số mặc định. Có một ngoại lệ: khi xác định giá trị tham số mặc định khi có chú thích loại, hãy thêm dấu cách trước và sau =.

Đúng

  1. def phức tạp(thực, hình ảnh=0.0): trả về Magic(r=thực tếTôi=hình ảnh 
  2. def phức tạp(thực, hình ảnh: trôi nổi = 0.0): trả về Magic(r=thực tếTôi=hình ảnh

KHÔNG

  1. def phức tạp(thực, hình ảnh = 0.0): trả về Magic(r = thực tếTôi = hình ảnh 
  2. def phức tạp(thực, hình ảnh: trôi nổi=0.0): trả về Magic(r = thực tếTôi = hình ảnh

Không sử dụng khoảng trắng để căn chỉnh không cần thiết, vì điều này sẽ mang lại gánh nặng không cần thiết trong quá trình bảo trì (đối với: .#, =, v.v.).

Đúng

  1. đồ ăn = 1000  # bình luận  
  2. tên_dài = 2  # bình luận không nên căn chỉnh 
  3. từ điển = { 
  4.     'foo': 1,  
  5.     'tên_dài': 2,  

KHÔNG

  1. đồ ăn       = 1000  # bình luận 
  2. tên_dài = 2     # bình luận không nên căn chỉnh 
  3. từ điển = {  
  4.     'foo': 1,  
  5.     'tên_dài': 2,  
3.7 Sự việc

Hầu hết các tệp .py không cần bắt đầu bằng dòng #! Theo PEP-394, tệp chính của chương trình phải bắt đầu bằng #!/usr/bin/python2 hoặc #!/usr/bin/python3.

Dòng này được sử dụng để giúp kernel tìm trình thông dịch Python, nhưng bị Python bỏ qua khi nhập mô-đun/chỉ cần thiết trong các tệp sẽ được chạy trực tiếp.

3.8 Nhận xét và tài liệu

Đảm bảo sử dụng đúng chuỗi tài liệu và nhận xét nội tuyến cho mô-đun, hàm và phương thức.

3.8.1 Chuỗi tài liệu.

Python sử dụng chuỗi tài liệu để tạo tài liệu cho mã. Chuỗi tài liệu là câu lệnh đầu tiên của gói, mô-đun, lớp hoặc hàm. Các chuỗi này có thể được trích xuất tự động bằng phương thức thành viên __doc__ và được sử dụng bởi pydoc. trên đó để xem nó là gì). Sử dụng ba dấu ngoặc kép """ (theo PEP-257). Chuỗi tài liệu phải được sắp xếp như sau: tóm tắt một dòng (hoặc chỉ một dòng cho toàn bộ chuỗi tài liệu) và kết thúc bằng dấu chấm, lời chào hoặc dấu chấm than. Tiếp theo bằng một dòng trống, theo sau là Chuỗi tài liệu và căn chỉnh nó với dấu ngoặc kép đầu tiên của dòng đầu tiên. Thông số định dạng cụ thể hơn như sau. .

3.8.2 Mô-đun.

Mỗi tệp phải chứa một mẫu giấy phép. Chọn mẫu giấy phép phù hợp để sử dụng cho dự án (ví dụ: Apache 2.0, BSD, LGPL, GPL).

Tài liệu phải bắt đầu bằng một chuỗi tài liệu và mô tả nội dung của mô-đun cũng như cách sử dụng nó.

  1. """Tóm tắt một dòng về mô-đun hoặc chương trình, kết thúc bằng dấu chấm.  
  2. Để lại một dòng trống. Phần còn lại của docstring này phải chứa một  
  3. mô tả tổng thể của mô-đun hoặc chương trình. Tùy chọn, nó cũng có thể  
  4. chứa một mô tả ngắn gọn về các lớp và hàm đã xuất và/hoặc cách sử dụng  
  5. ví dụ.  
  6.   Ví dụ sử dụng điển hình:  
  7.   đồ ăn = Lớp học()  
  8.   thanh = đồ ăn.Thanh chức năng()  
  9. """ 

3.8.3 Chức năng và phương pháp.

Trong phần này, "hàm" bao gồm một phương thức, hàm hoặc trình tạo.

Hàm phải có chuỗi tài liệu trừ khi đáp ứng tất cả các điều kiện sau

  •  Không thể nhìn thấy từ bên ngoài
  •  rất ngắn
  •  ngắn gọn

Chuỗi tài liệu phải chứa đủ thông tin để gọi hàm mà không cần đọc mã của hàm. Chuỗi tài liệu phải mang tính tường thuật ("""Tìm nạp các hàng từ một Bigtable.""") thay vì bắt buộc ("" "Tìm nạp các hàng từ một Bigtable."" "), ngoại trừ @property (nên sử dụng cùng kiểu với thuộc tính). Chuỗi tài liệu nên mô tả cú pháp gọi hàm và ý nghĩa của hàm, thay vì cách triển khai. Các phần phức tạp hơn nằm trong đó. Sẽ thích hợp hơn khi sử dụng các nhận xét trong mã số. .

Các phương thức ghi đè một lớp cơ sở có thể có một chuỗi tài liệu đơn giản cho người đọc biết chuỗi tài liệu của phương thức được ghi đè, chẳng hạn như """Xem lớp cơ sở.""". lớp cơ sở ở nhiều nơi tồn tại trong chuỗi tài liệu. Tuy nhiên, nếu hành vi của phương thức ghi đè thực sự không nhất quán với phương thức được ghi đè hoặc cần cung cấp chi tiết (chẳng hạn như tài liệu chỉ ra các tác dụng phụ bổ sung), thì chuỗi tài liệu của phương pháp ghi đè ít nhất phải cung cấp những khác biệt đó.

Các khía cạnh khác nhau của một hàm phải được ghi lại trong các phần tương ứng, như sau. Mỗi phần phải bắt đầu bằng một dòng kết thúc bằng dấu hai chấm. Mỗi phần, ngoại trừ dòng đầu tiên, phải được thụt lề bằng 2 hoặc 4 dấu cách ở trước. tài liệu (người dịch khuyến nghị nên sử dụng 4 khoảng trắng để có tính nhất quán tổng thể). Nếu tên hàm và chữ ký đủ thông tin và có thể được mô tả chỉ bằng một dòng tài liệu thì những phần này có thể được bỏ qua.

Đối số

Liệt kê tên của từng tham số. Theo sau tên phải là dấu hai chấm và dấu cách, theo sau là phần mô tả. Nếu mô tả quá dài để vừa với một dòng 80 ký tự, thì hãy chia nó thành các dòng riêng biệt và thụt lề bằng. 2 hoặc 4 khoảng trắng và nhất quán với toàn bộ tài liệu (Người dịch cũng khuyến nghị nên sử dụng 4 khoảng trắng).

Mô tả phải bao gồm các loại tham số bắt buộc, nếu mã không chứa chú thích loại. Nếu hàm cho phép *foo (danh sách tham số có độ dài không xác định) hoặc **bar (tham số từ khóa tùy ý), thì nó phải được liệt kê trong chuỗi tài liệu. dưới dạng * foo và **bar .

Trả về: (hoặc Năng suất :) cho máy phát điện.

Mô tả loại và ý nghĩa của giá trị trả về. Nếu hàm trả về ít nhất là Không thì phần này không bắt buộc. Nếu chuỗi tài liệu bắt đầu bằng Trả về hoặc Kết quả (ví dụ: """Trả về hàng từ Bigtable dưới dạng một bộ chuỗi." "") hoặc phần đầu tiên Phần này có thể được bỏ qua nếu câu này đủ để mô tả giá trị trả về.

Tăng

Không nên liệt kê tất cả các ngoại lệ liên quan đến giao diện. Các ngoại lệ vi phạm các yêu cầu về tài liệu sẽ không được liệt kê (vì điều này nghịch lý là sẽ khiến hành vi vi phạm các yêu cầu giao diện trở thành một phần của giao diện).

  1. def fetch_bigtable_rows(big_table, keys, biến_ngớ_ngớ_khác=Không có):  
  2.     """Lấy các hàng từ Bigtable.  
  3.     Truy xuất các hàng liên quan đến các khóa đã cho từ phiên bản Table  
  4.     được biểu diễn bởi big_table. Những điều ngớ ngẩn có thể xảy ra nếu 
  5.     other_silly_variable không phải là None.  
  6.     Lập luận:  
  7.         big_table: Một thể hiện Bảng Bigtable mở.  
  8.         keys: Một chuỗi các chuỗi biểu diễn khóa của mỗi hàng trong bảng  
  9.             để lấy. 
  10.          other_silly_variable: Một biến tùy chọn khác, có nhiều  
  11.             tên dài hơn các đối số khác và không có tác dụng gì.    
  12.     Trả về:  
  13.         Một dict ánh xạ các khóa tới dữ liệu hàng bảng tương ứng  
  14.         đã lấy. Mỗi hàng được biểu diễn như một bộ chuỗi. Đối với  
  15.         ví dụ: 
  16.         {'Serak': ('Rigel VII', 'Người chuẩn bị'),  
  17.          'Zim': ('Irk', 'Kẻ xâm lược'),  
  18.          'Lrrr': ('Omicron Perseus 8', 'Hoàng đế')}  
  19.         Nếu một khóa từ đối số keys bị thiếu trong từ điển,  
  20.         thì hàng đó không được tìm thấy trong bảng.  
  21.     Tăng:  
  22.         IOError: Đã xảy ra lỗi khi truy cập đối tượng bigtable.Table. 
  23.      """ 

3.8.4 Lớp học.

Dòng tiếp theo của định nghĩa lớp phải là chuỗi tài liệu mô tả lớp. Nếu lớp có các thuộc tính công khai, chúng phải được ghi chú trong phần Thuộc tính của chuỗi tài liệu và phải nhất quán với phần Args của hàm.

  1. lớp SampleClass(đối tượng):  
  2.     """Tóm tắt lớp học ở đây.  
  3.     Thông tin lớp học dài hơn....  
  4.     Thông tin lớp học dài hơn....  
  5.     Thuộc tính:  
  6.         likes_spam: Giá trị boolean cho biết chúng ta có thích SPAM hay không.  
  7.         trứng: Số lượng nguyên của số trứng chúng ta đã đẻ.  
  8.     """  
  9.     định nghĩa __init__(bản thân, thích_thư rác=SAI):  
  10.         """Khởi tạo SampleClass với blah."""  
  11.         self.likes_spam = thích_thư rác  
  12.         trứng tự = 0 
  13.     def public_method(bản thân):  
  14.         """Thực hiện thao tác blah.""" 

3.8.5 Chặn bình luận và bình luận dòng.

Nơi cuối cùng để nhận xét trong mã là phần kỹ thuật của mã. Nếu bạn định tiết lộ mã trong phần đánh giá mã tiếp theo, bạn nên thêm nhận xét ngay bây giờ. Trước khi bắt đầu các thao tác phức tạp, hãy nhận xét một vài dòng. chưa rõ ràng thì thêm chú thích vào cuối dòng.

  1. # Chúng tôi sử dụng tìm kiếm từ điển có trọng số để tìm ra vị trí của i trong  
  2. # mảng. Chúng tôi ngoại suy vị trí dựa trên số lớn nhất  
  3. # trong mảng và kích thước mảng và sau đó thực hiện tìm kiếm nhị phân để  
  4. # lấy số chính xác.  
  5. nếu i & (i-1) == 0: # Đúng nếu i bằng 0 hoặc lũy thừa của 2. 

Để cải thiện khả năng đọc, nhận xét dòng phải theo sau ít nhất 2 khoảng trắng của mã và bắt đầu phần nhận xét bằng dấu #, theo sau là ít nhất 1 dấu cách.

Ngoài ra, đừng mô tả mã và cho rằng người đọc mã thành thạo Python hơn bạn (anh ta chỉ không biết bạn đang cố gắng làm gì).

3.8.6 Dấu câu, chính tả và ngữ pháp.

Chú ý đến dấu câu, chính tả và ngữ pháp sẽ dễ đọc hơn những bình luận viết kém.

Nhận xét phải dễ đọc như văn bản tường thuật, với cách viết hoa và dấu câu phù hợp. Trong nhiều trường hợp, các câu hoàn chỉnh sẽ dễ đọc hơn những câu bị hỏng. Các nhận xét ngắn hơn, chẳng hạn như nhận xét ở cuối dòng, đôi khi có thể khó đọc hơn. phong cách nhất quán xuyên suốt.

Mặc dù việc người đánh giá mã chỉ ra việc sử dụng dấu phẩy trong đó nên sử dụng dấu chấm phẩy có thể gây khó chịu, nhưng điều quan trọng là phải duy trì mức độ rõ ràng và dễ đọc cao trong mã nguồn của bạn, dấu câu, chính tả và ngữ pháp phù hợp có thể hữu ích. đạt được điều này.

3.9 Lớp

Nếu lớp không kế thừa từ các lớp cơ sở khác thì rõ ràng nó phải được kế thừa từ đối tượng, ngay cả khi đó là lớp lồng nhau.

Đúng

  1. lớp SampleClass(đối tượng):  
  2.     vượt qua  
  3. lớp OuterClass(đối tượng):  
  4.     lớp InnerClass(đối tượng):  
  5.         vượt qua  
  6. lớp ChildClass(ParentClass):  
  7.     """Rõ ràng là đã thừa hưởng từ một lớp khác rồi.""" 

KHÔNG

  1. lớp SampleClass:  
  2.     vượt qua 
  3. lớp OuterClass:  
  4.     lớp InnerClass:  
  5.         vượt qua 

Việc kế thừa từ lớp đối tượng đảm bảo rằng các thuộc tính có thể chạy chính xác trong Python2 và bảo vệ mã khỏi những điểm không tương thích tiềm ẩn trong Python3. Điều này cũng xác định đối tượng bao gồm __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__ và __str__, v.v. các phương pháp .

3.10 Chuỗi

Sử dụng định dạng hoặc % để định dạng một chuỗi Ngay cả khi các tham số đều là đối tượng chuỗi, bạn phải cân nhắc xem nên sử dụng + hay % và định dạng.

Đúng

  1. x = Một +b  
  2. x = '%s, %s!' % (mệnh lệnh, chửi thề)  
  3. x = '{}, {}'.format(đầu tiên, thứ hai)  
  4. x = 'tên: %s; điểm: %d' % (tên, n)  
  5. x = 'tên: {}; điểm: {}'.format(tên, n)  
  6. x = f'tên: {tên}; điểm: {n}'  # Python 3.6+ 

KHÔNG

  1. bảng_nhân_viên = ''  
  2. đối với họ, tên trong danh sách nhân viên:  
  3.     bảng_nhân_viên += '<tr><td>%s, %std>tr>' % (họ, tên)  
  4. bảng_nhân_viên += 'bàn>

Tránh sử dụng các toán tử + và += để tích lũy các chuỗi trong một vòng lặp, vì các chuỗi là đối tượng bất biến. Điều này tạo ra các biến tạm thời không cần thiết và khiến thời gian chạy tăng theo phương trình bậc hai thay vì tuyến tính. ''.join được dùng để nối các danh sách ở cuối vòng lặp (hoặc ghi từng chuỗi con vào bộ đệm io.BytesIO).

Đúng

  1. mặt hàng = ['<bàn>']  
  2. đối với họ, tên trong danh sách nhân viên:  
  3.     items.append('<tr><td>%s, %std>tr>' % (họ, tên))  
  4. items.append('bàn>') 
  5. bảng_nhân_viên = ''.join(mục) 

KHÔNG

  1. bảng_nhân_viên = ''  
  2. đối với họ, tên trong danh sách nhân viên:  
  3.     bảng_nhân_viên += '<tr><td>%s, %std>tr>' % (họ, tên)  
  4. bảng_nhân_viên += 'bàn>

Trong cùng một tệp, dấu ngoặc kép phải nhất quán, chọn '' hoặc "" và không thay đổi nó. Bạn có thể thay đổi nó khi cần tránh \\ thoát.

Đúng

  1. Python('Tại sao bạn lại che mắt?')  
  2. Gollum ("Tôi sợ lỗi xơ vải.")  
  3. Người kể chuyện ('"Tốt!" một người đánh giá Python vui vẻ nghĩ.') 

KHÔNG

  1. Python("Tại sao bạn lại che mắt?")  
  2. Gollum ('Sợi vải. Nó đốt cháy. Nó đốt cháy chúng ta.')  
  3. Gollum ("Luôn là kẻ đáng ghét. Luôn theo dõi. Luôn theo dõi.") 

Đối với chuỗi nhiều dòng, hãy sử dụng """ thay vì ''' cho chuỗi nhiều dòng, khi và chỉ khi bạn sử dụng ''' cho tất cả chuỗi không phải tài liệu. Chuỗi nhiều dòng và sử dụng ' cho chuỗi thông thường. có thể được sử dụng. Chuỗi tài liệu phải sử dụng """ bất kể.

Các chuỗi nhiều dòng được thụt lề không nhất quán với phần còn lại của mã. Nếu bạn cần tránh chèn thêm dấu cách vào chuỗi, hãy sử dụng nối chuỗi một dòng hoặc chuỗi nhiều dòng với textwarp.dedent() để loại bỏ dấu cách thụt lề của mỗi dòng. .

KHÔNG

  1. chuỗi dài = """Điều này thật là xấu xí.  
  2. Đừng làm thế này. 
  3. """ 

Đúng

  1. chuỗi dài = """Điều này là tốt nếu trường hợp sử dụng của bạn có thể chấp nhận  
  2.     khoảng cách dẫn không cần thiết."""  
  3. chuỗi dài = ("Và điều này cũng ổn nếu bạn không thể chấp nhận\n" +  
  4.                "khoảng cách dẫn thừa.")  
  5. chuỗi dài = ("Và điều này cũng ổn nếu bạn không thể chấp nhận\n"  
  6.                "khoảng cách dẫn thừa.")  
  7. nhập textwrap  
  8. chuỗi dài = văn bản bọc.dedent("""\ 
  9.     Điều này cũng tốt, vì textwrap.dedent()  
  10.     sẽ thu gọn các khoảng cách dòng chung ở mỗi dòng.""") 
3.11 Tệp và ổ cắm

Đóng tập tin hoặc ổ cắm một cách rõ ràng khi sử dụng xong.

Việc mở tệp, ổ cắm hoặc các đối tượng giống tệp khác một cách không cần thiết có nhiều nhược điểm:

  •  Chúng có thể tiêu tốn tài nguyên hệ thống hạn chế, chẳng hạn như bộ mô tả tệp. Nếu hệ thống không được trả về ngay lập tức trong quá trình sử dụng, mã xử lý nhiều đối tượng như vậy có thể lãng phí rất nhiều tài nguyên không nên lãng phí.
  •  Việc giữ một tập tin có thể ngăn cản các thao tác khác như di chuyển hoặc xóa.
  •  Các tệp và ổ cắm được chia sẻ bởi các chương trình có thể vô tình được đọc và ghi ngay cả khi chúng đã được đóng một cách hợp lý. Nếu chúng thực sự bị đóng, các nỗ lực đọc hoặc ghi sẽ đưa ra một ngoại lệ, do đó vấn đề có thể được phát hiện ngay lập tức.

Ngoài ra, khi tệp hoặc ổ cắm tự động đóng khi đối tượng tệp bị hủy, không thể liên kết vòng đời của tệp với trạng thái tệp.

  •  Không có gì đảm bảo khi nào đối tượng tệp sẽ thực sự bị hủy. Các trình thông dịch Python khác nhau sử dụng các kỹ thuật quản lý bộ nhớ khác nhau. Ví dụ: việc xử lý rác bị trì hoãn có thể kéo dài vòng đời của đối tượng vô thời hạn.
  •  Có thể gây ra các tham chiếu không mong muốn đến các đối tượng tệp, chẳng hạn như trong các biến toàn cục hoặc theo dõi ngoại lệ, điều này có thể khiến đối tượng tệp tồn tại lâu hơn dự kiến.

Nên sử dụng câu lệnh with để quản lý tập tin

  1. với open("hello.txt") là hello_file:  
  2.     cho dòng trong hello_file:  
  3.         in(dòng) 

Đối với các đối tượng giống như tệp, nếu câu lệnh with không được hỗ trợ, bạn có thể sử dụng contextlib.closing()

  1. nhập contextlib  
  2. với contextlib.closing(urllib.urlopen("http://www.python.org/")) làm front_page: 
  3.     cho dòng ở front_page:  
  4.         in(dòng) 
3.12 Ý kiến ​​TODO

Sử dụng các nhận xét TODO cho các giải pháp tạm thời, ngắn hạn hoặc các giải pháp đủ tốt nhưng chưa hoàn hảo.

Nhận xét TODO bắt đầu bằng chuỗi TODO viết hoa toàn bộ, theo sau là tên, địa chỉ email hoặc vấn đề khác được viết trong dấu ngoặc đơn để xác định người chịu trách nhiệm hoặc chứa mô tả đúng nhất về vấn đề. đây.

Mục đích của việc có một kiểu TODO thống nhất là để tạo điều kiện thuận lợi cho việc tìm kiếm và hiểu cách lấy thêm các chi tiết liên quan. TODO không đảm bảo rằng người được đề cập sẽ khắc phục được sự cố. Vì vậy, về cơ bản, khi tạo nhận xét TODO, về cơ bản hãy cung cấp tên của bạn.

  1. # TODO(kl@gmail.com): Sử dụng dấu "*" ở đây để lặp lại chuỗi.  
  2. # TODO(Zeke) Thay đổi mục này để sử dụng quan hệ. 

Nếu nhận xét TODO có định dạng "Điều gì sẽ được thực hiện vào một thời điểm nào đó trong tương lai", hãy đảm bảo đưa ra một thời điểm rất cụ thể (ví dụ: "sẽ được sửa trước tháng 11 năm 2009") hoặc đưa ra một sự kiện rất cụ thể (ví dụ: "Xóa mã này khi tất cả máy khách có thể xử lý phản hồi XML").

3.13 định dạng nhập

Ví dụ: nhập khẩu phải ở các dòng khác nhau.

Đúng

  1. nhập khẩu chúng  
  2. nhập khẩu hệ thống 

KHÔNG

  1. nhập hệ điều hành, hệ thống 

Nội dung nhập phải được đặt ở đầu tệp, sau các nhận xét và chuỗi tài liệu của mô-đun cũng như trước các hằng số và toàn cục của mô-đun. Các nhóm phải được sắp xếp theo thứ tự từ phổ biến nhất đến ít phổ biến nhất.

  1. Nhập câu lệnh trong các phiên bản Python trong tương lai, ví dụ: .

  1. từ __future__ nhập absolute_import  
  2. từ __future__ nhập khẩu phân chia  
  3. từ __future__ nhập print_function 

Xem ở trên để biết thêm thông tin.

  2. Nhập thư viện cơ bản tiêu chuẩn Python, ví dụ: .

  1. nhập khẩu hệ thống 

  3. Nhập các thư viện hoặc gói của bên thứ ba, ví dụ: .

  1. nhập tensorflow dưới dạng tf 

  4. Nhập các gói con trong cơ sở mã, ví dụ: .

  1. từ otherproject.ai nhập tâm trí 

  5. Bài viết này không được dùng nữa: đây là bản nhập chuyên dụng cho cùng gói con cấp cao nhất như tệp hiện tại, ví dụ: .

  1. từ myproject.backend.hgwells nhập time_machine 

Điều này thực tế đã được thực hiện trong các phiên bản cũ hơn của hướng dẫn về phong cách mã hóa Google Python nhưng nó không còn cần thiết nữa. **Các kiểu mã hóa mới không còn gặp phải vấn đề này nữa.** Chỉ cần nhập gói phụ chuyên dụng và các gói phụ khác. Nhập có thể được xử lý tương tự.

Trong mỗi nhóm, sắp xếp theo thứ tự từ điển của đường dẫn gói hoàn chỉnh của từng mô-đun, bỏ qua trường hợp. Bạn có thể thêm các dòng trống trong mỗi phần của QC tùy theo tình huống.

  1. nhập bộ sưu tậpnhập hàng đợinhập hệ thống 
  2. từ absl nhập ứng dụngtừ absl nhập flagimport bs4import cryptographyimport tensorflow as tf  
  3. từ book.genres nhập scifitừ myproject.backend.hgwells nhập time_machinetừ myproject.backend.state_machine nhập main_looptừ otherproject.ai nhập bodytừ otherproject.ai nhập mindtừ otherproject.ai nhập soul 
  4. # Mã kiểu cũ có thể có các mục nhập này ở đây thay thế: 
  5. # Kiểu mã của phiên bản cũ có thể sử dụng phương thức nhập sau 
  6. # từ myproject.backend.hgwells nhập time_machine 
  7. # từ myproject.backend.state_machine nhập main_loop 
 3.14 Tuyên bố

Chỉ có một tuyên bố trên mỗi dòng.

Tuy nhiên, nếu câu lệnh kiểm tra và kết quả có thể được đặt trên một dòng thì chúng có thể được đặt trên một dòng. Tuy nhiên, câu lệnh thử/ngoại trừ và nội dung tương ứng không được phép đặt trên một dòng, vì cả hai đều không thử và ngoại trừ. có thể được hoàn thành trong một dòng. Đối với nếu không có câu lệnh khác có thể kết hợp nếu và nội dung tương ứng thành một dòng.

Đúng

  1. nếu foo: bar(foo) 

KHÔNG

  1. nếu foo: bar(foo)  
  2. khác: baz(foo)  
  3. thử: bar(foo)  
  4. ngoại trừ ValueError: baz(foo)  
  5. thử:  
  6.     thanh(foo) 
  7.  ngoại trừ ValueError: baz(foo) 
3.15 Truy cập

Đối với các hàm truy cập tầm thường và ít quan trọng hơn, hãy sử dụng các biến công khai để thay thế các hàm truy cập nhằm tránh sử dụng thêm lệnh gọi chương trình. Khi thêm nhiều hàm hơn, hãy sử dụng các thuộc tính để duy trì tính liên tục.

Ngoài ra, nếu quyền truy cập quá phức tạp hoặc chi phí truy cập biến quá cao, nên sử dụng quyền truy cập chức năng như get_foo() và set_foo() (xem hướng dẫn đặt tên nếu phương thức truy cập trước đây là thông qua các thuộc tính). , chức năng truy cập mới không được liên kết với thuộc tính để cách sử dụng thuộc tính cũ sẽ không hợp lệ và người dùng sẽ biết rằng chức năng đã thay đổi.

3.16 Đặt tên

tên_mô-đun, tên_gói, Tên_lớp, tên_phương_thức, Tên_ngoại_lệ, tên_hàm, TÊN_HỆ_THÔNG_THÔNG_Toàn_Cầu, tên_biến_toàn_cầu, tên_biến_thể_thể, tên_tham_số_hàm, tên_biến_cục_bộ.

Việc đặt tên hàm, tên biến, tên file phải mang tính mô tả, tránh viết tắt, đặc biệt là những từ viết tắt mơ hồ, xa lạ với người đọc và không rút ngắn bằng cách xóa các chữ cái trong từ.

Sử dụng .py làm phần mở rộng tệp và không sử dụng dấu gạch nối.

3.16.1 Những tên cần tránh:

  •  Tên một ký tự, trừ khi nó là phần tử đếm hoặc lặp, e có thể được sử dụng làm Tên phân biệt bắt ngoại lệ.
  •  -Dấu gạch ngang không được xuất hiện trong bất kỳ tên gói hoặc tên mô-đun nào
  •  __double_lead_and_trailing_underscore__ là tên có dấu gạch dưới kép ở đầu và cuối. Loại tên này là tên dành riêng có sẵn của Python.

3.16.4 Quy ước đặt tên.

  •  Các phương tiện nội bộ chỉ có sẵn trong mô-đun hoặc được bảo vệ hoặc riêng tư trong lớp
  •  Một dấu gạch dưới (_) ở đầu cho biết rằng nó được bảo vệ (từ quá trình nhập mô-đun * sẽ không được nhập). Một biến thể hiện hoặc phương thức bắt đầu bằng dấu gạch dưới kép (__, còn được gọi là "dunder") cho biết rằng nó là riêng tư. trong lớp (sử dụng sửa đổi tên). Chúng tôi không khuyến khích Sử dụng vì nó sẽ làm giảm khả năng đọc và khả năng kiểm tra. Giai đoạn II không thực sự là độc quyền.
  •  Các lớp liên quan và các hàm cấp cao nhất được đặt trong cùng một mô-đun. Không cần thiết phải đặt một lớp trong một mô-đun như Java.
  •  Sử dụng chữ in hoa cho tên lớp (chẳng hạn như CapWords), cách đặt tên và tên mô-đun phải là chữ thường và gạch chân. Mặc dù có một số cách đặt tên mô-đun cũ bằng chữ in hoa (chẳng hạn như CapWords.py), cách này hiện không được khuyến khích, vì nó. có thể gây nhầm lẫn khi mô-đun được đặt tên từ một lớp nhất định (ví dụ: bạn nên chọn import StringIO hay from StringIO import StringIO?)
  •  Trong phương thức unittest, có thể tách các thành phần của tên bằng cách bắt đầu bằng test, ngay cả khi các thành phần này ở dạng chữ hoa lạc đà. Phương pháp này được chấp nhận: test_ Ví dụ: testPop_EmptyStack, đối với tên được đặt tên. phương pháp thử nghiệm không có Cách chính xác rõ ràng.

3.16.3 Tên tập tin.

Phần mở rộng tệp phải là .py và không thể chứa -. Điều này đảm bảo rằng nó có thể được nhập và kiểm tra đơn vị một cách bình thường. Nếu bạn muốn một tệp thực thi được gọi mà không có phần mở rộng, hãy tạo một liên kết mềm hoặc gói bash đơn giản. "$0.py" "$@".

3.16.4 Hướng dẫn và đề xuất của Guido.

  。

kiểu công cộng nội bộ
Cái túi thấp hơn với bên dưới  
mô-đun thấp hơn với bên dưới _thấp_có_dưới
loại Từ vựng _Từ viết tắt
bất thường Từ vựng  
chức năng lower_with_under() _lower_with_under()
Hằng số toàn cầu/lớp CHỮ HOA CÓ DƯỚI _CAPS_CÓ_DƯỚI
Biến toàn cục/lớp thấp hơn với bên dưới _thấp_có_dưới
biến thể hiện thấp hơn với bên dưới _thấp_có_dưới(được bảo vệ)
tên phương thức lower_with_under() _lower_with_under()(được bảo vệ)
tham số hàm/phương thức thấp hơn với bên dưới  
biến cục bộ thấp hơn với bên dưới  

  。

Mặc dù Python hỗ trợ tư nhân hóa thông qua dấu gạch dưới kép__ (tức là "dunder"), nhưng điều này không được khuyến khích. Ưu tiên các dấu gạch dưới đơn dễ nhập hơn, dễ đọc hơn và dễ gọi hơn với các thử nghiệm đơn vị nhỏ. Các mối lo ngại về cảnh báo của Lint sẽ bị ảnh hưởng. truy cập không hợp lệ.

3.17 Chính

Ngay cả tệp py được sử dụng làm tập lệnh cũng có thể được nhập và khi nó chỉ được sử dụng để nhập, sẽ không có tác dụng phụ nào khi thực thi hàm chính. Hàm của hàm chính phải được đặt trong main().

Trong Python, thử nghiệm pydoc và đơn vị yêu cầu mô-đun có thể nhập được. Do đó, phải kiểm tra mã nếu __name__ == '__main__': trước khi chương trình chính được thực thi để ngăn mô-đun được thực thi khi được nhập.

  1. định nghĩa main():  
  2.     ...  
  3. nếu như __tên__ == '__chính__':  
  4.     chủ yếu() 

Tất cả mã cấp cao nhất được thực thi khi mô-đun được nhập. Do đó, hãy cẩn thận không gọi các hàm, tạo đối tượng hoặc thực hiện các thao tác khác không nên thực hiện khi thực thi pydoc.

3.18 Độ dài hàm

Ưu tiên viết các chức năng nhỏ, tập trung.

Hàm dài đôi khi cũng phù hợp nên không có giới hạn cố định về độ dài hàm. Nhưng khi vượt quá 40 dòng, bạn cần cân nhắc xem có nên phân tách hàm mà không ảnh hưởng đến cấu trúc chương trình hay không.

Mặc dù hiện tại các hàm dài chạy tốt, nhưng khi những hàm khác sửa đổi hàm và thêm các hàm mới trong tương lai, các lỗi mới có thể xuất hiện và khó tìm ra. Việc giữ hàm ngắn gọn sẽ giúp người khác hiểu và sửa đổi mã ..

Khi làm việc với một số mã, bạn có thể thấy rằng một số hàm dài và phức tạp. Đừng ngại điều chỉnh mã hiện có. Nếu việc làm việc với hàm đó gặp khó khăn, chẳng hạn như việc gỡ lỗi hoặc bạn muốn sử dụng nó trong một số ngữ cảnh khác nhau. , sau đó thay đổi chức năng Chia nó thành các phần nhỏ hơn, dễ kiểm soát hơn.

3.19 Loại chú thích

3.19.1 Quy tắc cơ bản.

  •  Làm quen với PEP-484
  •  Trong phương thức, chỉ thêm thông tin loại thích hợp vào self hoặc cls khi cần thiết. Ví dụ: @classmethod def create(cls: Type[T]) -> T: return cls().
  •  Nếu các biến hoặc kiểu trả về khác là biến, hãy sử dụng Any
  •  Không cần chú thích mọi chức năng
    •   Ít nhất giao diện công cộng cần phải được chỉ định
    •   Sử dụng kiểm tra kiểu để cân bằng sự an toàn với sự rõ ràng và linh hoạt trong khai báo
    •   Đánh dấu mã có xu hướng ném ngoại lệ do các vấn đề liên quan đến loại (lỗi trước hoặc độ phức tạp, người dịch ở đây cho rằng nó phù hợp với mã trước, cân bằng giữa bảo mật và độ phức tạp)
    •   Chú thích mã khó hiểu
    •   Chú thích mã ổn định loại, mã trưởng thành và ổn định có thể được chú thích mà không ảnh hưởng đến tính linh hoạt của nó.

3.19.2 Chi nhánh.

Thực hiện theo các quy ước thụt lề hiện có.

Sau khi đánh dấu loại, hầu hết các chữ ký hàm phải là "một tham số trên mỗi dòng".

  1. def my_method(bản thân,  
  2.               biến đầu tiên: int,  
  3.               giây_var: Foo,  
  4.               third_var: Tùy chọn[Bar]) -> số nguyên:  
  5.   ... 

Ưu tiên ngắt dòng giữa các biến thay vì ở nơi khác (chẳng hạn như giữa tên biến và loại nhận xét). Nếu tất cả có thể vừa trên một dòng, hãy đặt nó trên một dòng.

  1. def my_method(self, first_var: int) -> số nguyên:  
  2.   ... 

Nếu tên hàm, tham số cuối cùng và nhận xét kiểu trả về quá dài trên một dòng, hãy ngắt dòng và thụt lề 4 dấu cách.

  1. def phương pháp của tôi(  
  2.     tự, first_var: int) -> Bộ[MyLongType1, MyLongType1]:
  3.   ... 

Khi loại giá trị trả về không thể được đặt trên cùng một dòng với tham số cuối cùng, cách tốt hơn để xử lý nó là tách các tham số thành các dòng riêng biệt và thụt lề chúng bằng 4 dấu cách, đồng thời bọc khung bên phải và loại giá trị trả về trong một dòng mới và căn chỉnh chúng với def.

  1. def phương pháp của tôi(  
  2.     self, other_arg: Tùy chọn[MyLongType]  
  3. ) -> Dict[OtherLongType, MyLongType]:  
  4.   ... 

pylint cho phép bạn di chuyển dấu ngoặc đóng sang một dòng mới và căn chỉnh nó với dấu ngoặc mở, nhưng điều này không dễ hiểu.

KHÔNG

  1. def my_method(bản thân,  
  2.               other_arg: Tùy chọn[MyLongType]  
  3.              ) -> Dict[OtherLongType, MyLongType]: 
  4.    ... 

Cũng giống như ví dụ trên, cố gắng không chia các nhận xét loại, nhưng đôi khi các nhận xét loại quá dài để vừa trên một dòng (sau đó cố gắng không chia các nhận xét phụ).

  1. def phương pháp của tôi(  
  2.     bản thân,  
  3.     first_var: Tuple[Danh sách[MyLongType1], 
  4.                      Danh sách[MyLongType2]],  
  5.     second_var: Danh sách[Dict[  
  6.         MyLongType3, MyLongType4]]) -> Không có: 
  7.    ... 

Nếu tên hoặc loại quá dài, hãy cân nhắc sử dụng bí danh. Nếu không có giải pháp nào khác, hãy thụt lề mỗi dòng 4 dấu cách sau dấu hai chấm.

Đúng

  1. định nghĩa hàm của tôi(  
  2.     tên_biến_dài:  
  3.         tên_mô-đun_dài.LongTypeName,  
  4. ) -> Không có:  
  5.   ... 

KHÔNG

  1. định nghĩa hàm của tôi(  
  2.     tên_biến_dài: tên_mô_đun_dài.  
  3.         Tên dài,) -> Không có:  
  4.   ... 

3.19.3 Tuyên bố trước.

Nếu bạn cần một tên lớp chưa được xác định trong cùng một mô-đun, chẳng hạn như một lớp bên trong một khai báo lớp hoặc một lớp cần được xác định trong mã tiếp theo, hãy sử dụng chuỗi tên lớp thay thế.

  1. lớp MyClass(đối tượng): 
  2.    định nghĩa __init__(bản thân,  
  3.                stack: List["MyClass"]) -> Không có: 

3.19.4 Giá trị mặc định.

Tham khảo PEP-008, chỉ thêm dấu cách trước và sau = khi yêu cầu cả chú thích loại và giá trị mặc định.

Đúng

  1. định nghĩa hàm(a: số nguyên = 0) -> số nguyên:  
  2.   ... 

KHÔNG

  1. định nghĩa hàm(a:int=0) -> số nguyên: 
  2.   ... 

3.19.5 Không có loại nào 。

Trong hệ thống Python, NoneType là loại hạng nhất. Để thuận tiện cho việc nhập liệu, None là bí danh của NoneType. Nếu một tham số có thể là None thì nó cần được khai báo. gõ, sau đó sử dụng Tùy chọn.

Sử dụng Tùy chọn một cách rõ ràng thay vì ngầm định. Các phiên bản đầu tiên của PEP 484 cho phép a: Text = None được hiểu là: Tùy chọn[Text] = None.

Đúng

  1. def func(a: Tùy chọn[Văn bản], b: Tùy chọn[Văn bản] = Không có) -> Chữ:  
  2.   ...  
  3. def multiple_nullable_union(a: Union[Không có, Văn bản, int]) -> Chữ 
  4.   ... 

KHÔNG

  1. def nullable_union(a: Union[Không có, Văn bản]) -> Chữ:  
  2.   ...  
  3. def implicit_optional(a: Chữ = Không có) -> Chữ:  
  4.   ... 

3.19.6 Nhập bí danh.

Bí danh có thể được khai báo cho các loại phức tạp. Tên của bí danh phải là CapWorded. Nếu nó chỉ được sử dụng trong mô-đun hiện tại thì nó phải được gạch chân và tư nhân hóa.

Ví dụ: nếu tên loại có tên mô-đun quá dài

  1. _Tên viết tắt = module_with_long_name.TypeWithLongName  
  2. Bản đồ phức tạp = Bản đồ[Văn bản, Danh sách[Tuple[int, int]]] 

Các ví dụ khác là các kiểu lồng nhau phức tạp và nhiều biến trả về (dưới dạng bộ dữ liệu) từ một hàm.

3.19.7 Bỏ qua việc kiểm tra loại.

Việc kiểm tra loại có thể bị vô hiệu hóa bằng cách thêm nhận xét dòng đặc biệt #type:ignore .

pytype có tùy chọn đóng để báo cáo lỗi rõ ràng (tương tự như lint)

  1. # Kiểu dữ liệu: vô hiệu hóa=thuộc tính-lỗi 

3.19.8 Chú thích loại biến.

Chú thích kiểu biến Nếu khó hoặc không thể trỏ đến biến nội bộ, bạn có thể sử dụng phương pháp sau:

chú thích kiểu

Thêm nhận xét bắt đầu bằng #type ở cuối dòng.

  1. Một = Một số hàm chưa được trang trí() # loại: Foo 

Ràng buộc chú thích

Sử dụng dấu hai chấm và nhập giữa tên biến và phép gán, phù hợp với các tham số của hàm.

  1. Một: Đồ ăn = Một số hàm chưa được trang trí() 

3.19.9 Bộ dữ liệu và danh sách.

Không giống như danh sách, chỉ có thể chứa một loại duy nhất, bộ dữ liệu có thể có một loại lặp lại hoặc một tập hợp các phần tử thuộc các loại khác nhau, loại sau thường được sử dụng khi hàm được trả về.

  1. Một = [1, 2, 3] # kiểu: List[int]  
  2. b = (1, 2, 3) # kiểu: Tuple[int, ...]  
  3. c = (1, "2", 3.5) # kiểu: Tuple[int, Text, float] 

3.19.10 Biến kiểu 。

Python có các khái niệm chung và hàm TypeVar là cách phổ biến để sử dụng nó.

ví dụ

  1. từ việc nhập danh sách, TypeVar  
  2. T = KiểuVar("T")  
  3. ...  
  4. def next(l: List[T]) -> T: 
  5.   trả về l.pop() 

TypeVar có thể hạn chế các loại

  1. Loại có thể thêm = KiểuVar("AddableType", int, float, Văn bản)  
  2. def add(a: AddableType, b: AddableType) -> Loại có thể thêm:  
  3.     trả về a + b 

Biến loại được xác định trước trong mô-đun gõ là AnyStr, được sử dụng để duy trì nhiều chú thích loại nhất quán với các chuỗi có thể là byte hoặc unicode.

  1. từ việc nhập AnyStr  
  2. def check_length(x: AnyStr) -> Bất kỳ chuỗi nào:  
  3.   nếu len(x) <= 42: 
  4.     trả lại x  
  5.   nâng cao ValueError() 

3.19.11 Kiểu chuỗi.

Loại thích hợp cho chuỗi nhận xét dựa trên phiên bản Python.

Đối với mã chỉ Python3, hãy sử dụng str, Văn bản có thể được sử dụng nhưng vẫn nhất quán trong lựa chọn.

Đối với mã tương thích với Python 2, hãy sử dụng Văn bản và trong một số trường hợp hiếm hoi, str có thể có sẵn. Điều này thường được thực hiện để đảm bảo tính tương thích khi loại giá trị trả về khác nhau giữa các phiên bản Python khác nhau. Tránh sử dụng unicode vì nó không tồn tại trong phiên bản Python. Python3 ..

KHÔNG

  1. định nghĩa py2_code(x: chuỗi) -> mã hóa:  
  2.   ... 

Đối với mã xử lý dữ liệu nhị phân, hãy sử dụng byte.

Đúng

  1. def deals_with_binary_data(x: byte) -> byte:  
  2.   ... 

Để tương thích với Python2, mã xử lý dữ liệu văn bản (str hoặc unicode trong Python, str trong Python3), hãy sử dụng Text.

  1. từ việc nhập văn bản nhập khẩu  
  2. ...  
  3. def py2_compatible(x: Văn bản) -> Chữ:  
  4.   ...  
  5. định nghĩa py3_only(x: chuỗi) -> chuỗi:  
  6.   ... 

Nếu nó có thể là cả byte và văn bản, hãy sử dụng Union và loại văn bản thích hợp.

  1. từ việc nhập văn bản, Union  
  2. ...  
  3. def py2_compatible(x: Union[byte, Văn bản]) -> Union[byte, Văn bản]:  
  4.   ... 
  5.  def py3_only(x: Union[byte, str]) -> Hợp nhất[byte, chuỗi]:  
  6.   ... 

Nếu tất cả các loại chuỗi trong một hàm luôn nhất quán, ví dụ: loại giá trị trả về và loại tham số trong ví dụ trước đều nhất quán, thì hãy sử dụng AnyStr.

Viết như thế này có thể đơn giản hóa quá trình di chuyển mã sang Python3.

3.19.12 nhập nhập.

Đối với các lớp được nhập từ mô-đun gõ, hãy nhập chính lớp đó được phép nhập nhiều lớp cụ thể từ mô-đun gõ trong một dòng, chẳng hạn như.

  1. từ nhập nhập Bất kỳ, Dict, Tùy chọn 

Phương pháp nhập từ mô-đun gõ này sẽ thêm các mục bổ sung vào không gian tên. Bất kỳ tên nào khi gõ phải được coi giống như từ khóa và không được xác định trong mã Python của bạn, có gõ hay không (người dịch suy đoán bài viết có được giới thiệu hay không) .Nếu nó xung đột với cách đặt tên hiện có, hãy sử dụng import x as y để nhập.

  1. từ việc nhập nhập Any như AnyType 

3.19.13 Nhập khẩu có điều kiện.

Chỉ sử dụng nhập có điều kiện khi phải tránh kiểm tra loại trong thời gian chạy. Mẫu này không được khuyến khích. Các giải pháp thay thế như tái cấu trúc mã để cho phép nhập cấp cao nhất được khuyến khích.

Có thể đặt các nội dung nhập chỉ được sử dụng cho chú thích loại vào các khối if TYPE_CHECKING:.

  •  Loại nhập có điều kiện phải được coi là tham chiếu chuỗi để tương thích với Python 3.6 (trong Python 3.6, biểu thức chú thích thực sự được gán).
  •  Chỉ những trường hợp được sử dụng riêng cho chú thích kiểu mới có thể được xác định ở đây, bao gồm cả bí danh. Nếu không, lỗi thời gian chạy sẽ được báo cáo vì các mô-đun này sẽ không được tham chiếu trong thời gian chạy.
  •  Khối mã sẽ ngay lập tức tuân theo quá trình nhập thông thường.
  •  Không được có dòng trống sau khi nhập kiểu
  •  Sắp xếp khối mã này theo thứ tự nhập thông thường. 
  1. nhập khẩu đánh máy  
  2. nếu gõ .TYPE_CHECKING:  
  3.     nhập bản phác thảo  
  4. def f(x: "sketch.Sketch"): ... 

3.19.14 Phụ thuộc vòng tròn.

Vì các phụ thuộc vòng tròn do kiểm tra loại gây ra có mùi mã nên mã đó phải được cấu trúc lại. Mặc dù về mặt kỹ thuật có thể duy trì các tham chiếu vòng tròn nhưng hệ thống xây dựng không cho phép điều này vì mỗi mô-đun phải phụ thuộc vào các mô-đun khác...

Thay thế mô-đun gây ra sự phụ thuộc vòng tròn bằng Any và đặt cho nó một bí danh có ý nghĩa và sử dụng tên lớp thực được nhập từ mô-đun này (vì bất kỳ thuộc tính nào của Any là Any). Định nghĩa của bí danh được phân tách khỏi dòng nhập cuối cùng bằng một dấu a. dòng trống ..

  1. từ nhập nhập Bất kỳ  
  2. một số_mod = Bất kì  # some_mod.py nhập mô-đun này.  
  3. ...  
  4. def my_method(self, var: some_mod.SomeType) -> Không có:  
  5.   ... 

3.19.15 Thuốc gốc.

Khi chú thích, ưu tiên dành cho các tham số loại cụ thể theo loại chung, nếu không các tham số chung sẽ được coi là Bất kỳ.

  1. def get_names(employee_ids: Danh sách[int]) -> Dict[int, Bất kỳ]:  
  2.   ... 
  1. # Cả hai đều được diễn giải là get_names(employee_ids: List[Any]) -> Dict[Bất kỳ, Bất kỳ]  
  2. def get_names(employee_ids: danh sách) -> Từ điển:  
  3.   ...  
  4. def get_names(employee_ids: Danh sách) -> Từ điển:  
  5.   ... 

Nếu loại tham số tốt nhất của một generic là Any thì nó sẽ được nêu rõ ràng. Nhưng trong nhiều trường hợp, TypeVar có thể phù hợp hơn.

  1. def get_names(employee_ids: List[Any]) -> Dict[Bất kỳ, Văn bản]: 
  2. """Trả về ánh xạ từ ID nhân viên tới tên nhân viên cho các ID đã cho.""" 
  1. T = KiểuVar('T')  
  2. def get_names(employee_ids: Danh sách[T]) -> Dict[T, Văn bản]:  
  3. """Trả về ánh xạ từ ID nhân viên tới tên nhân viên cho các ID đã cho.""" 

4. Lời cuối cùng

  。

Nếu bạn đang chỉnh sửa mã, hãy dành vài phút để xem mã hiện có và quyết định nên sử dụng kiểu nào. Nếu mã hiện có thêm khoảng trắng xung quanh tất cả các toán tử số học, bạn cũng nên làm như vậy. Nếu các nhận xét hiện có Sử dụng dấu thăng để tạo thành một. hộp giới hạn, vì vậy nhận xét của bạn cũng nên làm như vậy.

Mục đích của việc có hướng dẫn về phong cách viết mã là để có được sự đồng thuận về lập trình để mọi người có thể tập trung vào nội dung hơn là hình thức. Chúng tôi xuất bản hướng dẫn về phong cách viết mã chung ở đây để mọi người có thể hiểu được sự đồng thuận này (Người dịch: Có một Tháp Babel Ý nghĩa. .) Nhưng kiểu mã hóa tương ứng của chúng cũng rất quan trọng. Nếu mã bạn thêm trông hoàn toàn không phù hợp với mã gốc, nó sẽ làm gián đoạn nhịp đọc của người đọc. Hãy tránh điều này.

Liên kết gốc: https://mp.weixin.qq.com/s/YghgDFu8V2EWVlzxInW_.

Cuối cùng, bài viết về hướng dẫn kiểu mã Python nội bộ của Google kết thúc ở đây. Nếu bạn muốn biết thêm về hướng dẫn kiểu mã Python nội bộ của Google, vui lòng tìm kiếm bài viết CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ nó trong tương lai. blog! .

40 4 0
qq735679552
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress