Các ví dụ cụ thể về Python của Python chỉ có một cách để làm điều đó max max [đã đóng]


34

Tôi đang học Python và bị thu hút bởi điểm sau trong PEP 20 Zen của Python :

Nên có một-- và tốt nhất là chỉ có một cách rõ ràng để làm điều đó. Mặc dù cách đó ban đầu có thể không rõ ràng trừ khi bạn là người Hà Lan.

Bất cứ ai có thể cung cấp bất kỳ ví dụ cụ thể của câu châm ngôn này? Tôi đặc biệt quan tâm đến sự tương phản với các ngôn ngữ khác như Ruby. Một phần của triết lý thiết kế Ruby (bắt nguồn từ Perl, tôi nghĩ vậy?) Là nhiều cách thực hiện nó là Một điều tốt. Bất cứ ai cũng có thể đưa ra một số ví dụ cho thấy những ưu và nhược điểm của từng phương pháp. Lưu ý, tôi không theo câu trả lời nào tốt hơn (có lẽ quá chủ quan chưa từng được trả lời), mà là so sánh không thiên vị giữa hai phong cách.

Câu trả lời:


47

So với các ngôn ngữ như Perl, Python có số lượng cấu trúc điều khiển hạn chế:

  • chỉ ifvà không unless,
  • chỉ forđiều đó lặp đi lặp lại theo trình tự và không foreachhoặc kiểu C for,
  • chỉ whilekiểm tra một điều kiện mỗi vòng lặp và không do-while,
  • chỉ if-elifvà không switch,
  • chỉ có một cấu trúc nhận xét #, và cho mỗi dòng bạn có thể biết liệu nó có được nhận xét hay không, mà không cần nhìn vào các dòng trước đó.

Ngoài ra, có gần một cách để thụt lề nguồn của bạn; hầu hết các trường hợp thụt sáng tạo được loại trừ về mặt cú pháp.

Điều này làm cho việc phân tích một nguồn Python dễ dàng hơn cho con người.

Có những nỗ lực để được tối thiểu nhưng đầy đủ trong các loại tích hợp và thư viện chuẩn.

  • đối với danh sách có thể thay đổi, bạn sử dụng loại tích hợp duy nhất list; đó là O (1) cho hầu hết các hoạt động và bạn không bao giờ phải chọn thực hiện đúng,
  • Đối với các danh sách bất biến, bằng nhau, bạn chỉ cần sử dụng tupleloại,
  • đối với bản đồ, bạn sử dụng công cụ tích hợp duy nhất có dicthiệu quả trong hầu hết các trường hợp, không cần phải suy nghĩ về việc sử dụng triển khai nào.

Python 3 mở rộng điều này cho các số nguyên: cho dù số nguyên của bạn lớn đến đâu, bạn vẫn sử dụng cùng loại và không bao giờ quan tâm đến việc ép buộc.

Python cố gắng tránh đường cú pháp. Nhưng đôi khi nó thêm đường cú pháp chỉ để làm cho cách rõ ràng rõ ràng. Bạn có thể viết if foo is not Nonethay if not (foo is None)vì bởi vì 'không' là đặc biệt. Vẫn foo is not Noneđọc dễ dàng, không thể bị hiểu sai, và bạn không cần phải suy nghĩ, bạn chỉ cần viết điều rõ ràng.

Tất nhiên, hầu hết những điều phức tạp hơn trong Python có thể được thực hiện theo nhiều cách. Bạn có thể thêm các phương thức vào các lớp bằng cách khai báo hoặc bằng cách gán vị trí đơn giản, bạn có thể chuyển các đối số cho các hàm theo một số cách sáng tạo, v.v. Điều đó chỉ vì phần bên trong của ngôn ngữ hầu hết được phơi bày.

Điều quan trọng là luôn có một cách được dự định là tốt nhất, bao gồm tất cả. Nếu các cách khác tồn tại, chúng không được thêm vào như là các lựa chọn thay thế bằng nhau (như ifunless) mà chỉ phơi bày các hoạt động bên trong. Dần dần nhưng dần dần các lựa chọn thay thế như vậy đã bị lỗi thời (không bị loại bỏ!) Bằng cách tăng cường cơ chế tốt nhất được biết đến.

Trang trí bọc chức năng gọi AOP. Trước 2.6 bạn phải sử dụng __metaclass__thành viên ma thuật để khai báo siêu dữ liệu của một lớp; bây giờ bạn cũng có thể sử dụng cú pháp trang trí tương tự cho việc này. Trước 3.0, bạn có hai loại chuỗi, định hướng byte và Unicode, mà bạn có thể vô tình trộn lẫn. Bây giờ bạn chỉ có Unicode strvà nhị phân duy nhất trong suốt bytesmà bạn không thể nhầm lẫn.


3
Cũng như một ghi chú, đừng quên """bình luận (tài liệu). Những khoảng này nhiều dòng.
asthasr

8
Các chữ ba trích dẫn chỉ là các chuỗi, giống như các trích dẫn đơn, nhưng có thể kéo dài nhiều dòng mà không thoát khỏi các đầu dòng. Một chuỗi ký tự ngay sau khi khai báo được coi là một chuỗi doc và nó không phải là một nhận xét, nó thường có thể truy cập như một __doc__thuộc tính. Nhưng chuỗi là một lĩnh vực mà Python chắc chắn cung cấp nhiều 'cách đúng': sử dụng trích dẫn đơn, đôi hoặc ba, ngầm tham gia các chữ liền kề, sử dụng rcho các chữ thô, v.v.
9000

1
Tôi nghĩ rằng nhận xét của @ syrion liên quan đến "bạn luôn có thể quyết định xem một dòng có được nhận xét hay không bằng cách chỉ nhìn vào nó", điều này không đúng vì các chuỗi "" ".
blubb

2
"Điều này làm cho việc phân tích nguồn Python dễ dàng hơn cho con người." <- đó là chủ quan
nhộn

Làm thế nào để khai báo metaclass thay đổi trong 2.7? Không thể tìm thấy mẫu trang trí trong 2.7 tài liệu cho siêu dữ liệu.
Nick T

10

Một vài ví dụ khác là:
len()là một hàm thay vì một phương thức có trong mọi chuỗi; nếu bạn so sánh với Java bạn có .length, .size(), .getSize(), và các phương pháp khác để tìm số phần tử trong một chuỗi.

Một ví dụ khác là thực tế .join()là một stringphương thức, không phải là một phương thức có trong mọi trình tự. Bạn không cần biết tham số tham gia là danh sách, tập hợp, mức độ hiểu hay bất cứ điều gì, nó sẽ hoạt động.


8

Trong C có nhiều cách có thể để tăng giá trị của biến lên một:

i++     // Post-increment, returns the number before the increment
++i     // Pre-increment, returns the number after the increment
i += 1 

Mỗi kết thúc lên tăng giá trị của ibằng 1, nhưng mỗi là hơi khác nhau.

Trong Python, thực sự chỉ có một cách; chỉ cần thêm một.

i += 1

Và mặc dù có nhiều hơn một cách hợp lệ để thực hiện điều này (ví dụ i = i + 1), bạn đang làm điều tương tự với các tác dụng phụ tương tự.


1
Tôi không phải là chuyên gia, nhưng ví dụ đó dường như vi phạm chính xác ý tưởng "chỉ có một cách để làm điều đó". Chúng ta có hai cách để làm điều đó, nhưng cái nào rõ ràng hơn? Trước mắt tôi, ví dụ đầu tiên rõ ràng hơn trong khi ví dụ thứ hai ngắn gọn hơn nhưng không kém phần dễ đọc hoặc rõ ràng đối với bất kỳ lập trình viên nào đã tiến bộ vượt ra ngoài những điều cơ bản. Cảm ơn câu trả lời của bạn - đó là thức ăn tốt cho suy nghĩ.
Charles Roper

@Peter (và @Charles): Trên thực tế, i = i + 1là sự phân công, không phải là sự gia tăng. Trong python một sự gia tăng là i += 1. Trong ngôn ngữ C-phong cách bạn có thể viết i++, ++ii += 1.
Josh K

2
Không chắc chắn về nhận xét "nhiều nhầm lẫn" của bạn, cả ba ví dụ C của bạn (bạn đã bỏ lỡ i += 1, BTW) đều tạo ra kết quả chính xác như nhau. Lần duy nhất tôi thấy mọi người bị lẫn lộn là khi họ trước hoặc sau tăng một biến như một phần của biểu thức lớn hơn và điều đó thường nhanh chóng được khắc phục bằng cách đọc phần thích hợp của tài liệu tham khảo ngôn ngữ. Cá nhân, tôi đã chọn thực tế là bạn có thể đề cập đến ký tự thứ năm của chuỗi bằng cả hai str[4]hoặc *(str+4), nhưng có lẽ điều đó quá dễ dàng ...
TMN

2
@TMN: một số trường hợp, như max(i++, ++i)không thể được khắc phục nhanh chóng. C có rất nhiều trường hợp hành vi "không xác định" và "phụ thuộc vào việc thực hiện", tất cả đều có lý do chính đáng - nhưng mỗi trường hợp có thể tạo ra một cạm bẫy.
9000

@TMN: Chưa kể 4 [str] (hợp lệ trong C, có thể không hợp lệ trong C ++).
Vatine

6

Một khả năng khác có thể là danh sách hiểu. Trong Python, bạn có thể làm điều này:

new_list = []
    for item in list_of_items:
       if item < 10:
           new_list.append(item)

Nhưng cách "rõ ràng" (nếu bạn là người Hà Lan hoặc quen thuộc hơn với Python) khi thực hiện việc này sẽ bằng cách hiểu danh sách:

new_list = [item for item in list_of_items if item < 10]

Nó ngắn hơn, new_list được tạo trong một bước, tôi tin rằng nó chạy nhanh hơn và nó rất thanh lịch. Mặt khác, người ta có thể tranh luận rằng nó cảm thấy ít rõ ràng hơn, nhưng tôi nghĩ một khi bạn đã quen với nó, nó chỉ là rõ ràng.


Đối với thụt lề và mã: đặt trước nó với 4 khoảng trắng, sau đó nó sẽ tôn trọng thụt lề.
Inca
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.