Python là khai báo hay thủ tục?

Mô hình lập trình là một cách tiếp cận để giải quyết vấn đề bằng một số ngôn ngữ lập trình hoặc chúng ta cũng có thể nói đó là một phương pháp để giải quyết vấn đề bằng các công cụ và kỹ thuật có sẵn cho chúng ta theo một số cách tiếp cận. Có rất nhiều ngôn ngữ lập trình được biết đến nhưng tất cả chúng đều cần tuân theo một số chiến lược khi chúng được triển khai và phương pháp/chiến lược này là mô hình. Ngoài các loại ngôn ngữ lập trình, có rất nhiều mô hình để đáp ứng từng nhu cầu

Mô hình lập trình

Lập trình mệnh lệnh như tên gợi ý là một loại mô hình lập trình mô tả cách chương trình thực thi. Các nhà phát triển quan tâm nhiều hơn đến cách từng bước nhận được câu trả lời. Nó bao gồm chuỗi mệnh lệnh mệnh lệnh. Trong đó, thứ tự thực hiện là rất quan trọng và sử dụng cả dữ liệu có thể thay đổi và không thể thay đổi. Các ngôn ngữ lập trình Fortran, Java, C, C++ là những ví dụ về lập trình mệnh lệnh.  

Lập trình khai báo như tên gợi ý là một loại mô hình lập trình mô tả chương trình nào sẽ được thực thi. Các nhà phát triển quan tâm nhiều hơn đến câu trả lời nhận được. Nó tuyên bố loại kết quả nào chúng ta muốn và bỏ ngôn ngữ lập trình sang một bên để tập trung vào việc tìm ra cách tạo ra chúng. Nói một cách đơn giản, nó chủ yếu tập trung vào kết quả cuối cùng. Nó thể hiện tính logic của tính toán. Miranda, Erlang, Haskell, Prolog là một vài ví dụ phổ biến về lập trình khai báo

Sau khi hiểu được những kiến ​​thức cơ bản về cả hai ngôn ngữ, bây giờ chúng ta hãy thảo luận về sự khác biệt chính giữa hai loại lập trình khác nhau này

Trong tài liệu này, chúng ta sẽ xem các tính năng của Python phù hợp để triển khai các chương trình theo kiểu chức năng. Sau khi giới thiệu về các khái niệm về lập trình hàm, chúng ta sẽ xem xét các tính năng ngôn ngữ như s và s và các mô-đun thư viện có liên quan như và

Giới thiệu

Phần này giải thích khái niệm cơ bản về lập trình chức năng;

Ngôn ngữ lập trình hỗ trợ phân tách vấn đề theo nhiều cách khác nhau

  • Hầu hết các ngôn ngữ lập trình là thủ tục. chương trình là danh sách các hướng dẫn cho máy tính biết phải làm gì với đầu vào của chương trình. C, Pascal và thậm chí Unix shell là các ngôn ngữ thủ tục

  • Trong các ngôn ngữ khai báo, bạn viết một đặc tả mô tả vấn đề cần giải quyết và ngôn ngữ triển khai tìm ra cách thực hiện tính toán hiệu quả. SQL là ngôn ngữ khai báo mà bạn có thể quen thuộc nhất;

  • Các chương trình hướng đối tượng thao tác các tập hợp các đối tượng. Các đối tượng có trạng thái bên trong và hỗ trợ các phương thức truy vấn hoặc sửa đổi trạng thái bên trong này theo một cách nào đó. Smalltalk và Java là ngôn ngữ hướng đối tượng. C++ và Python là những ngôn ngữ hỗ trợ lập trình hướng đối tượng, nhưng không bắt buộc sử dụng các tính năng hướng đối tượng

  • Lập trình chức năng phân tách một vấn đề thành một tập hợp các chức năng. Lý tưởng nhất là các hàm chỉ nhận đầu vào và tạo đầu ra và không có bất kỳ trạng thái bên trong nào ảnh hưởng đến đầu ra được tạo cho một đầu vào nhất định. Các ngôn ngữ chức năng nổi tiếng bao gồm họ ML [ML tiêu chuẩn, OCaml và các biến thể khác] và Haskell

Các nhà thiết kế của một số ngôn ngữ máy tính chọn nhấn mạnh một cách tiếp cận cụ thể để lập trình. Điều này thường gây khó khăn khi viết chương trình sử dụng cách tiếp cận khác. Các ngôn ngữ khác là ngôn ngữ đa mô hình hỗ trợ một số cách tiếp cận khác nhau. Lisp, C++ và Python là đa mô hình; . Trong một chương trình lớn, các phần khác nhau có thể được viết bằng các cách tiếp cận khác nhau;

Trong một chương trình chức năng, đầu vào chảy qua một tập hợp các chức năng. Mỗi chức năng hoạt động trên đầu vào của nó và tạo ra một số đầu ra. Kiểu chức năng không khuyến khích các chức năng có tác dụng phụ sửa đổi trạng thái bên trong hoặc thực hiện các thay đổi khác không hiển thị trong giá trị trả về của chức năng. Các chức năng hoàn toàn không có tác dụng phụ được gọi là chức năng thuần túy. Tránh tác dụng phụ có nghĩa là không sử dụng cấu trúc dữ liệu được cập nhật khi chương trình chạy;

Một số ngôn ngữ rất nghiêm ngặt về độ tinh khiết và thậm chí không có các câu lệnh gán chẳng hạn như

for line in file:
    # do something for each line
    ...
2 hoặc
for line in file:
    # do something for each line
    ...
3, nhưng rất khó để tránh tất cả các tác dụng phụ, chẳng hạn như in ra màn hình hoặc ghi vào tệp đĩa. Một ví dụ khác là một lệnh gọi hàm hoặc, cả hai hàm này đều không trả về giá trị hữu ích. Cả hai chỉ được gọi vì tác dụng phụ của chúng là gửi một số văn bản tới màn hình hoặc tạm dừng thực thi trong một giây

Các chương trình Python được viết theo kiểu chức năng thường sẽ không đi đến mức cực đoan là tránh tất cả I/O hoặc tất cả các nhiệm vụ; . Ví dụ: việc triển khai một hàm sẽ vẫn sử dụng phép gán cho các biến cục bộ, nhưng sẽ không sửa đổi các biến toàn cục hoặc có các tác dụng phụ khác

Lập trình hàm có thể được coi là đối lập với lập trình hướng đối tượng. Các đối tượng là những viên nang nhỏ chứa một số trạng thái bên trong cùng với một tập hợp các lệnh gọi phương thức cho phép bạn sửa đổi trạng thái này và các chương trình bao gồm việc thực hiện đúng tập hợp các thay đổi trạng thái. Lập trình hàm muốn tránh thay đổi trạng thái càng nhiều càng tốt và hoạt động với dữ liệu chảy giữa các hàm. Trong Python, bạn có thể kết hợp hai cách tiếp cận bằng cách viết các hàm nhận và trả về các thể hiện đại diện cho các đối tượng trong ứng dụng của bạn [e-mail, giao dịch, v.v. ]

Thiết kế theo chức năng có vẻ như là một hạn chế kỳ lạ để làm việc theo. Tại sao bạn nên tránh các đối tượng và tác dụng phụ?

  • khả năng chứng minh chính thức

  • tính mô đun

  • Khả năng kết hợp

  • Dễ gỡ lỗi và thử nghiệm

khả năng chứng minh chính thức

Một lợi ích về mặt lý thuyết là việc xây dựng một bằng chứng toán học rằng một chương trình chức năng là đúng sẽ dễ dàng hơn.

Trong một thời gian dài, các nhà nghiên cứu đã quan tâm đến việc tìm cách chứng minh các chương trình đúng về mặt toán học. Điều này khác với việc thử nghiệm một chương trình trên nhiều đầu vào và kết luận rằng đầu ra của nó thường đúng hoặc đọc mã nguồn của chương trình và kết luận rằng mã đó có vẻ đúng;

Kỹ thuật được sử dụng để chứng minh chương trình đúng là viết ra các bất biến, thuộc tính của dữ liệu đầu vào và của các biến của chương trình luôn đúng. Đối với mỗi dòng mã, sau đó bạn chỉ ra rằng nếu các bất biến X và Y là đúng trước khi dòng được thực thi, thì các bất biến hơi khác một chút X’ và Y’ là đúng sau khi dòng được thực thi. Điều này tiếp tục cho đến khi bạn kết thúc chương trình, tại thời điểm đó, các bất biến phải khớp với các điều kiện mong muốn trên đầu ra của chương trình

Lập trình chức năng tránh các nhiệm vụ phát sinh vì các nhiệm vụ khó xử lý bằng kỹ thuật này;

Thật không may, việc chứng minh chương trình đúng phần lớn là không thực tế và không liên quan đến phần mềm Python. Ngay cả các chương trình tầm thường cũng yêu cầu bằng chứng dài vài trang; . Ngay cả khi bạn đã viết ra hoặc tạo ra một bằng chứng, thì sẽ có câu hỏi về việc xác minh bằng chứng đó;

tính mô đun

Một lợi ích thiết thực hơn của lập trình hàm là nó buộc bạn phải chia nhỏ vấn đề của mình thành từng phần nhỏ. Kết quả là các chương trình có tính mô-đun hơn. Việc chỉ định và viết một hàm nhỏ thực hiện một việc sẽ dễ dàng hơn so với một hàm lớn thực hiện một phép biến đổi phức tạp. Các hàm nhỏ cũng dễ đọc và dễ kiểm tra lỗi hơn

Dễ gỡ lỗi và thử nghiệm

Kiểm tra và gỡ lỗi chương trình kiểu chức năng dễ dàng hơn

Gỡ lỗi được đơn giản hóa vì các chức năng thường nhỏ và được chỉ định rõ ràng. Khi một chương trình không hoạt động, mỗi chức năng là một điểm giao diện nơi bạn có thể kiểm tra xem dữ liệu có chính xác không. Bạn có thể xem các đầu vào và đầu ra trung gian để nhanh chóng cô lập chức năng gây ra lỗi

Kiểm tra dễ dàng hơn vì mỗi chức năng là một chủ đề tiềm năng cho một bài kiểm tra đơn vị. Các chức năng không phụ thuộc vào trạng thái hệ thống cần được sao chép trước khi chạy thử nghiệm;

Khả năng kết hợp

Khi bạn làm việc trên một chương trình kiểu hàm, bạn sẽ viết một số hàm với các đầu vào và đầu ra khác nhau. Một số chức năng này chắc chắn sẽ được chuyên biệt hóa cho một ứng dụng cụ thể, nhưng những chức năng khác sẽ hữu ích trong nhiều chương trình khác nhau. Ví dụ, một hàm lấy đường dẫn thư mục và trả về tất cả các tệp XML trong thư mục hoặc một hàm lấy tên tệp và trả về nội dung của nó, có thể được áp dụng cho nhiều tình huống khác nhau

Theo thời gian, bạn sẽ hình thành một thư viện tiện ích cá nhân. Thông thường, bạn sẽ lắp ráp các chương trình mới bằng cách sắp xếp các chức năng hiện có trong một cấu hình mới và viết một số chức năng chuyên biệt cho tác vụ hiện tại

vòng lặp

Tôi sẽ bắt đầu bằng cách xem xét một tính năng của ngôn ngữ Python, đây là nền tảng quan trọng để viết các chương trình kiểu chức năng. vòng lặp

Trình vòng lặp là một đối tượng đại diện cho một luồng dữ liệu; . Trình lặp Python phải hỗ trợ một phương thức được gọi là không có đối số và luôn trả về phần tử tiếp theo của luồng. Nếu không còn phần tử nào trong luồng, phải tăng ngoại lệ. Tuy nhiên, các trình vòng lặp không nhất thiết phải là hữu hạn;

Hàm tích hợp nhận một đối tượng tùy ý và cố gắng trả về một trình vòng lặp sẽ trả về nội dung hoặc phần tử của đối tượng, tăng nếu đối tượng không hỗ trợ phép lặp. Một số kiểu dữ liệu có sẵn của Python hỗ trợ phép lặp, phổ biến nhất là danh sách và từ điển. Một đối tượng được gọi nếu bạn có thể lấy một trình vòng lặp cho nó

Bạn có thể thử nghiệm giao diện lặp theo cách thủ công

>>> L = [1, 2, 3]
>>> it = iter[L]
>>> it  

>>> it.__next__[]  # same as next[it]
1
>>> next[it]
2
>>> next[it]
3
>>> next[it]
Traceback [most recent call last]:
  File "", line 1, in 
StopIteration
>>>

Python mong đợi các đối tượng có thể lặp lại trong một số ngữ cảnh khác nhau, quan trọng nhất là câu lệnh. Trong câu lệnh

>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13
2, Y phải là một trình lặp hoặc một đối tượng nào đó có thể tạo một trình lặp. Hai tuyên bố này là tương đương

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]

Các trình lặp có thể được cụ thể hóa dưới dạng danh sách hoặc bộ dữ liệu bằng cách sử dụng hàm tạo hoặc

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]

Trình tự giải nén cũng hỗ trợ các trình vòng lặp. nếu bạn biết một trình vòng lặp sẽ trả về N phần tử, bạn có thể giải nén chúng thành một N-tuple

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]

Các hàm tích hợp như và có thể nhận một đối số trình vòng lặp duy nhất và sẽ trả về phần tử lớn nhất hoặc nhỏ nhất. Các toán tử

>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13
8 và
>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13
9 cũng hỗ trợ các trình vòng lặp.
>>> line_list = ['  line 1\n', 'line 2  \n', ' \n', '']

>>> # Generator expression -- returns iterator
>>> stripped_iter = [line.strip[] for line in line_list]

>>> # List comprehension -- returns list
>>> stripped_list = [line.strip[] for line in line_list]
0 là đúng nếu X được tìm thấy trong luồng được trả về bởi trình vòng lặp. Bạn sẽ gặp vấn đề rõ ràng nếu trình vòng lặp là vô hạn;

Lưu ý rằng bạn chỉ có thể đi tiếp trong một trình vòng lặp; . Các đối tượng iterator có thể tùy chọn cung cấp các khả năng bổ sung này, nhưng giao thức iterator chỉ xác định phương thức. Do đó, các chức năng có thể sử dụng tất cả đầu ra của trình vòng lặp và nếu bạn cần làm điều gì đó khác với cùng một luồng, bạn sẽ phải tạo một trình vòng lặp mới

Các kiểu dữ liệu hỗ trợ Iterator

Chúng ta đã thấy cách danh sách và bộ dữ liệu hỗ trợ trình vòng lặp. Trên thực tế, bất kỳ loại trình tự Python nào, chẳng hạn như chuỗi, sẽ tự động hỗ trợ tạo trình vòng lặp

Gọi từ điển trả về một trình vòng lặp sẽ lặp qua các khóa của từ điển

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12

Lưu ý rằng bắt đầu với Python 3. 7, thứ tự lặp lại từ điển được đảm bảo giống với thứ tự chèn. Trong các phiên bản trước, hành vi không được chỉ định và có thể khác nhau giữa các lần triển khai

Áp dụng cho một từ điển luôn lặp lại các khóa, nhưng từ điển có các phương thức trả về các trình vòng lặp khác. Nếu bạn muốn lặp lại các giá trị hoặc cặp khóa/giá trị, bạn có thể gọi phương thức hoặc một cách rõ ràng để nhận một trình lặp thích hợp

Hàm tạo có thể chấp nhận một trình vòng lặp trả về một luồng hữu hạn gồm các bộ dữ liệu

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
1

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}

Các tệp cũng hỗ trợ lặp bằng cách gọi phương thức cho đến khi không còn dòng nào trong tệp. Điều này có nghĩa là bạn có thể đọc từng dòng của một tệp như thế này

for line in file:
    # do something for each line
    ...

Các bộ có thể lấy nội dung của chúng từ một lần lặp và cho phép bạn lặp lại các phần tử của bộ

>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13

Biểu thức trình tạo và hiểu danh sách

Hai thao tác phổ biến trên đầu ra của iterator là 1] thực hiện một số thao tác cho mọi phần tử, 2] chọn một tập hợp con các phần tử đáp ứng một số điều kiện. Ví dụ: đưa ra một danh sách các chuỗi, bạn có thể muốn loại bỏ khoảng trắng ở cuối mỗi dòng hoặc trích xuất tất cả các chuỗi chứa một chuỗi con đã cho

Liệt kê khả năng hiểu và biểu thức trình tạo [dạng ngắn. “listcomps” và “genexps”] là một ký hiệu ngắn gọn cho các hoạt động như vậy, mượn từ ngôn ngữ lập trình chức năng Haskell [https. //www. haskell. tổ chức/]. Bạn có thể loại bỏ tất cả khoảng trắng khỏi một luồng chuỗi bằng đoạn mã sau

>>> line_list = ['  line 1\n', 'line 2  \n', ' \n', '']

>>> # Generator expression -- returns iterator
>>> stripped_iter = [line.strip[] for line in line_list]

>>> # List comprehension -- returns list
>>> stripped_list = [line.strip[] for line in line_list]

Bạn chỉ có thể chọn một số phần tử nhất định bằng cách thêm điều kiện

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
3

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]

Với khả năng hiểu danh sách, bạn lấy lại danh sách Python; . Các biểu thức trình tạo trả về một trình vòng lặp tính toán các giá trị khi cần thiết, không cần cụ thể hóa tất cả các giá trị cùng một lúc. Điều này có nghĩa là khả năng hiểu danh sách không hữu ích nếu bạn đang làm việc với các trình vòng lặp trả về một luồng vô hạn hoặc một lượng dữ liệu rất lớn. Biểu thức trình tạo thích hợp hơn trong những tình huống này

Biểu thức trình tạo được bao quanh bởi dấu ngoặc đơn [“[]”] và cách hiểu danh sách được bao quanh bởi dấu ngoặc vuông [“[]”]. Biểu thức trình tạo có dạng

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
0

Một lần nữa, để hiểu danh sách, chỉ có các dấu ngoặc bên ngoài là khác nhau [dấu ngoặc vuông thay vì dấu ngoặc đơn]

Các phần tử của đầu ra được tạo sẽ là các giá trị kế tiếp của

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
5. Các mệnh đề
>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
6 đều là tùy chọn;

Biểu thức trình tạo luôn phải được viết bên trong dấu ngoặc đơn, nhưng dấu ngoặc đơn báo hiệu lệnh gọi hàm cũng được tính. Nếu bạn muốn tạo một trình vòng lặp sẽ được chuyển ngay đến một hàm, bạn có thể viết

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
1

Các mệnh đề

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
9 chứa các chuỗi được lặp lại. Các chuỗi không nhất thiết phải có cùng độ dài vì chúng được lặp từ trái sang phải, không song song. Đối với mỗi phần tử trong
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
00,
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
01 được lặp lại từ đầu. Sau đó,
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
02 được lặp lại cho từng cặp phần tử kết quả từ
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
00 và
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
01

Nói cách khác, một biểu thức hiểu danh sách hoặc trình tạo danh sách tương đương với mã Python sau

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
2

Điều này có nghĩa là khi có nhiều mệnh đề

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
9 nhưng không có mệnh đề
>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
6, thì độ dài của kết quả đầu ra sẽ bằng tích độ dài của tất cả các chuỗi. Nếu bạn có hai danh sách có độ dài 3, danh sách đầu ra dài 9 phần tử

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
3

Để tránh đưa sự mơ hồ vào ngữ pháp của Python, nếu

>>> stripped_list = [line.strip[] for line in line_list
..                  if line != ""]
5 đang tạo một bộ, thì nó phải được bao quanh bởi dấu ngoặc đơn. Cách hiểu danh sách đầu tiên bên dưới là một lỗi cú pháp, trong khi cách hiểu thứ hai là đúng

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
4

máy phát điện

Trình tạo là một lớp hàm đặc biệt giúp đơn giản hóa tác vụ viết trình vòng lặp. Các hàm thông thường tính toán một giá trị và trả về giá trị đó, nhưng các trình tạo trả về một trình vòng lặp trả về một luồng giá trị

Chắc chắn bạn đã quen với cách hoạt động của các lệnh gọi hàm thông thường trong Python hoặc C. Khi bạn gọi một hàm, nó sẽ nhận được một không gian tên riêng nơi các biến cục bộ của nó được tạo. Khi hàm đạt đến câu lệnh

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
08, các biến cục bộ bị hủy và giá trị được trả về cho người gọi. Một cuộc gọi sau tới cùng một hàm sẽ tạo một không gian tên riêng mới và một tập hợp các biến cục bộ mới. Nhưng, nếu các biến cục bộ không bị loại bỏ khi thoát khỏi một hàm thì sao?

Đây là ví dụ đơn giản nhất về hàm tạo

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
5

Bất kỳ hàm nào chứa từ khóa đều là hàm tạo;

Khi bạn gọi một hàm tạo, nó không trả về một giá trị nào; . Khi thực hiện biểu thức

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09, trình tạo sẽ xuất ra giá trị của
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
11, tương tự như câu lệnh
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
08. Sự khác biệt lớn giữa câu lệnh
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 và câu lệnh
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
08 là khi đạt tới câu lệnh
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09, trạng thái thực thi của trình tạo bị tạm dừng và các biến cục bộ được giữ nguyên. Trong lần gọi tiếp theo đến phương thức của trình tạo, hàm sẽ tiếp tục thực thi

Đây là cách sử dụng mẫu của trình tạo

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
17

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
6

Bạn cũng có thể viết

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
18, hoặc
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
19

Bên trong một hàm tạo,

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
20 làm cho
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
21 được nâng lên từ phương thức. Khi điều này xảy ra hoặc đạt đến đáy của hàm, quá trình xử lý các giá trị kết thúc và trình tạo không thể tạo ra bất kỳ giá trị nào nữa

Bạn có thể đạt được hiệu ứng của trình tạo theo cách thủ công bằng cách viết lớp của riêng bạn và lưu trữ tất cả các biến cục bộ của trình tạo dưới dạng biến thể hiện. Ví dụ: trả về một danh sách các số nguyên có thể được thực hiện bằng cách đặt

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
23 thành 0 và tăng phương thức
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
23 rồi trả về. Tuy nhiên, đối với một trình tạo phức tạp vừa phải, việc viết một lớp tương ứng có thể phức tạp hơn nhiều

Bộ thử nghiệm đi kèm với thư viện của Python, Lib/test/test_generators. py, chứa một số ví dụ thú vị hơn. Đây là một trình tạo thực hiện duyệt theo thứ tự của cây bằng cách sử dụng trình tạo đệ quy

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
7

Hai ví dụ khác trong

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
26 đưa ra các giải pháp cho bài toán N-quân hậu [đặt N quân hậu trên một bàn cờ NxN sao cho không quân hậu nào đe dọa quân khác] và Chuyến đi của hiệp sĩ [tìm một con đường đưa quân mã đến mọi ô của bàn cờ NxN mà không cần đến thăm

Truyền giá trị vào trình tạo

Trong Python 2. 4 trở về trước, máy phát điện chỉ tạo ra công suất. Khi mã của trình tạo được gọi để tạo một trình vòng lặp, không có cách nào để chuyển bất kỳ thông tin mới nào vào hàm khi quá trình thực thi của nó được tiếp tục. Bạn có thể hack khả năng này cùng nhau bằng cách làm cho trình tạo xem xét một biến toàn cục hoặc bằng cách chuyển vào một số đối tượng có thể thay đổi mà người gọi sau đó sửa đổi, nhưng những cách tiếp cận này rất lộn xộn

Trong Python 2. 5, có một cách đơn giản để chuyển các giá trị vào trình tạo. đã trở thành một biểu thức, trả về một giá trị có thể được gán cho một biến hoặc hoạt động trên

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
8

Tôi khuyên bạn nên luôn đặt dấu ngoặc đơn xung quanh biểu thức

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 khi bạn đang làm gì đó với giá trị được trả về, như trong ví dụ trên. Dấu ngoặc đơn không phải lúc nào cũng cần thiết, nhưng sẽ dễ dàng hơn khi thêm chúng vào thay vì phải ghi nhớ khi cần thiết

[PEP 342 giải thích các quy tắc chính xác, đó là biểu thức

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 phải luôn được đặt trong ngoặc đơn trừ khi nó xuất hiện ở biểu thức cấp cao nhất ở phía bên tay phải của một phép gán. Điều này có nghĩa là bạn có thể viết
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
30 nhưng phải sử dụng dấu ngoặc đơn khi có phép toán, như trong
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
31. ]

Các giá trị được gửi vào một trình tạo bằng cách gọi phương thức của nó. Phương thức này tiếp tục mã của trình tạo và biểu thức

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 trả về giá trị đã chỉ định. Nếu phương thức thông thường được gọi, thì
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 trả về
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
36

Đây là một bộ đếm đơn giản tăng thêm 1 và cho phép thay đổi giá trị của bộ đếm bên trong

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
9

Và đây là một ví dụ về việc thay đổi bộ đếm

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
0

Bởi vì

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09 thường sẽ quay lại với
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
36, bạn phải luôn kiểm tra trường hợp này. Đừng chỉ sử dụng giá trị của nó trong các biểu thức trừ khi bạn chắc chắn rằng phương thức đó sẽ là phương thức duy nhất được sử dụng để tiếp tục chức năng trình tạo của bạn

Ngoài , có hai phương pháp khác trên máy phát điện

  • được sử dụng để đưa ra một ngoại lệ bên trong trình tạo;

  • đưa ra một ngoại lệ bên trong trình tạo để kết thúc quá trình lặp lại. Khi nhận được ngoại lệ này, mã của trình tạo phải tăng hoặc ; . cũng sẽ được gọi bởi trình thu gom rác của Python khi trình tạo được thu gom rác

    Nếu bạn cần chạy mã dọn dẹp khi xảy ra sự cố, tôi khuyên bạn nên sử dụng bộ

    for i in iter[obj]:
        print[i]
    
    for i in obj:
        print[i]
    
    50 thay vì bắt

Tác động tích lũy của những thay đổi này là biến những người tạo ra thông tin một chiều thành người sản xuất và người tiêu dùng.

Trình tạo cũng trở thành coroutines, một dạng tổng quát hơn của chương trình con. Các chương trình con được nhập vào tại một điểm và thoát ra tại một điểm khác [đỉnh của hàm và câu lệnh

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
08], nhưng các chương trình con có thể được nhập, thoát và tiếp tục tại nhiều điểm khác nhau [câu lệnh
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
09]

Chức năng tích hợp sẵn

Hãy xem chi tiết hơn về các hàm tích hợp thường được sử dụng với các trình vòng lặp

Hai trong số các hàm tích hợp sẵn của Python và sao chép các tính năng của biểu thức trình tạo

trả về một iterator qua chuỗi

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
57

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
1

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
2

Tất nhiên, bạn có thể đạt được hiệu quả tương tự với việc hiểu danh sách

trả về một trình vòng lặp trên tất cả các phần tử chuỗi đáp ứng một điều kiện nhất định và được sao chép tương tự bằng cách hiểu danh sách. Vị ngữ là một hàm trả về giá trị thực của một số điều kiện;

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
3

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
4

Điều này cũng có thể được viết dưới dạng hiểu danh sách

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
5

đếm các phần tử trong 2 bộ lặp trả về có thể lặp lại chứa số lượng [từ đầu] và từng phần tử

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
6

thường được sử dụng khi lặp qua một danh sách và ghi lại các chỉ mục mà tại đó các điều kiện nhất định được đáp ứng

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
7

thu thập tất cả các phần tử của iterable vào một danh sách, sắp xếp danh sách và trả về kết quả đã sắp xếp. Các đối số chính và đảo ngược được chuyển qua phương thức của danh sách được xây dựng

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
8

[Để thảo luận chi tiết hơn về sắp xếp, hãy xem. ]

Các và tích hợp xem xét các giá trị thực của nội dung của một lần lặp. trả về

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
67 nếu bất kỳ phần tử nào trong iterable là giá trị thực và trả về
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
67 nếu tất cả các phần tử đều là giá trị thực

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
9

lấy một phần tử từ mỗi lần lặp và trả về chúng trong một tuple

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
0

Nó không xây dựng danh sách trong bộ nhớ và sử dụng hết tất cả các trình vòng lặp đầu vào trước khi quay lại; . [Thuật ngữ kỹ thuật cho hành vi này là đánh giá lười biếng. ]

Trình lặp này được thiết kế để sử dụng với các lần lặp có cùng độ dài. Nếu các lần lặp có độ dài khác nhau, luồng kết quả sẽ có cùng độ dài với lần lặp ngắn nhất

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
1

Tuy nhiên, bạn nên tránh làm điều này vì một phần tử có thể được lấy từ các trình vòng lặp dài hơn và bị loại bỏ. Điều này có nghĩa là bạn không thể tiếp tục sử dụng các trình vòng lặp nữa vì bạn có nguy cơ bỏ qua một phần tử bị loại bỏ

Mô-đun itertools

Mô-đun chứa một số trình vòng lặp thường được sử dụng cũng như các chức năng để kết hợp một số trình vòng lặp. Phần này sẽ giới thiệu nội dung của mô-đun bằng cách hiển thị các ví dụ nhỏ

Các chức năng của mô-đun rơi vào một vài lớp rộng

  • Các hàm tạo một trình vòng lặp mới dựa trên một trình vòng lặp hiện có

  • Các hàm xử lý các phần tử của iterator làm đối số hàm

  • Các chức năng để chọn các phần của đầu ra của trình vòng lặp

  • Một chức năng để nhóm đầu ra của một iterator

Tạo trình vòng lặp mới

trả về một dòng vô hạn các giá trị cách đều nhau. Bạn có thể tùy chọn cung cấp số bắt đầu, mặc định là 0 và khoảng cách giữa các số, mặc định là 1

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
2

lưu một bản sao nội dung của một trình lặp được cung cấp và trả về một trình lặp mới trả về các phần tử của nó từ đầu đến cuối. Trình vòng lặp mới sẽ lặp lại các phần tử này vô tận

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
3

trả về phần tử được cung cấp n lần hoặc trả về phần tử vô tận nếu n không được cung cấp

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
4

lấy một số lượng tùy ý các lần lặp làm đầu vào và trả về tất cả các phần tử của lần lặp đầu tiên, sau đó là tất cả các phần tử của lần lặp thứ hai, v.v., cho đến khi tất cả các lần lặp đã cạn kiệt

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
5

trả về một luồng là một phần của trình vòng lặp. Với một đối số dừng duy nhất, nó sẽ trả về các phần tử dừng đầu tiên. Nếu bạn cung cấp chỉ mục bắt đầu, bạn sẽ nhận được các phần tử dừng-bắt đầu và nếu bạn cung cấp một giá trị cho bước, các phần tử sẽ bị bỏ qua tương ứng. Không giống như cắt chuỗi và danh sách của Python, bạn không thể sử dụng các giá trị âm cho bắt đầu, dừng hoặc bước

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
6

sao chép một iterator; . Nếu bạn không cung cấp giá trị cho n, giá trị mặc định là 2. Việc sao chép các trình vòng lặp yêu cầu lưu một số nội dung của trình vòng lặp nguồn, vì vậy điều này có thể tiêu tốn bộ nhớ đáng kể nếu trình vòng lặp lớn và một trong các trình vòng lặp mới được sử dụng nhiều hơn các trình vòng lặp khác

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
7

Gọi hàm trên phần tử

Mô-đun chứa một bộ hàm tương ứng với các toán tử của Python. Một số ví dụ là [thêm hai giá trị], [giống như

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
81] và [trả về một giá trị có thể gọi tìm nạp thuộc tính
for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
83]

giả định rằng iterable sẽ trả về một luồng các bộ dữ liệu và gọi hàm func bằng cách sử dụng các bộ dữ liệu này làm đối số

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
8

Lựa chọn các yếu tố

Một nhóm hàm khác chọn một tập hợp con các phần tử của trình vòng lặp dựa trên một vị từ

ngược lại với , trả về tất cả các phần tử mà vị từ trả về false

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> a, b, c = iterator
>>> a, b, c
[1, 2, 3]
9

trả về các phần tử miễn là vị từ trả về true. Khi vị từ trả về false, trình lặp sẽ báo hiệu kết thúc kết quả của nó

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
0

loại bỏ các phần tử trong khi vị ngữ trả về true, sau đó trả về phần còn lại của kết quả có thể lặp lại

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
1

nhận hai bộ lặp và chỉ trả về những phần tử dữ liệu mà phần tử tương ứng của bộ chọn là đúng, dừng bất cứ khi nào hết một trong hai

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
2

hàm tổ hợp

Trả về một iterator đưa ra tất cả các kết hợp r-tuple có thể có của các phần tử có trong iterable

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
3

Các phần tử trong mỗi bộ vẫn giữ nguyên thứ tự khi iterable trả về chúng. Ví dụ: số 1 luôn ở trước 2, 3, 4 hoặc 5 trong các ví dụ trên. Một hàm tương tự, , loại bỏ ràng buộc này theo thứ tự, trả về tất cả các cách sắp xếp có thể có độ dài r

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
4

Nếu bạn không cung cấp giá trị cho r thì độ dài của lần lặp được sử dụng, nghĩa là tất cả các phần tử được hoán vị

Lưu ý rằng các hàm này tạo ra tất cả các kết hợp có thể có theo vị trí và không yêu cầu nội dung của iterable là duy nhất

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
5

Bộ giống hệt nhau

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
92 xảy ra hai lần, nhưng hai chuỗi 'a' đến từ các vị trí khác nhau

Hàm nới lỏng một ràng buộc khác. các phần tử có thể được lặp lại trong một tuple duy nhất. Về mặt khái niệm, một phần tử được chọn cho vị trí đầu tiên của mỗi bộ và sau đó được thay thế trước khi phần tử thứ hai được chọn

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
6

Nhóm các yếu tố

Chức năng cuối cùng tôi sẽ thảo luận, là chức năng phức tạp nhất.

for i in iter[obj]:
    print[i]

for i in obj:
    print[i]
95 là một hàm có thể tính giá trị khóa cho từng phần tử được trả về bởi iterable. Nếu bạn không cung cấp chức năng chính, thì chìa khóa chỉ đơn giản là từng phần tử

thu thập tất cả các phần tử liên tiếp từ khả năng lặp bên dưới có cùng giá trị khóa và trả về một luồng gồm 2 bộ chứa giá trị khóa và một trình vòng lặp cho các phần tử có khóa đó

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
7

giả định rằng nội dung của iterable bên dưới sẽ được sắp xếp dựa trên khóa. Lưu ý rằng các trình lặp được trả về cũng sử dụng trình lặp bên dưới, vì vậy bạn phải sử dụng kết quả của trình lặp-1 trước khi yêu cầu trình lặp-2 và khóa tương ứng của nó

Mô-đun funcool

Mô-đun chứa một số chức năng bậc cao hơn. Hàm bậc cao hơn nhận một hoặc nhiều hàm làm đầu vào và trả về một hàm mới. Công cụ hữu ích nhất trong mô-đun này là chức năng

Đối với các chương trình được viết theo phong cách chức năng, đôi khi bạn sẽ muốn xây dựng các biến thể của các chức năng hiện có có một số tham số được điền vào. Hãy xem xét một hàm Python

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
00; . Điều này được gọi là "ứng dụng chức năng một phần"

Hàm tạo for nhận các đối số

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
05. Đối tượng kết quả có thể gọi được, vì vậy bạn chỉ cần gọi nó để gọi
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
06 với các đối số được điền vào

Đây là một ví dụ nhỏ nhưng thực tế

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
8

thực hiện tích lũy một thao tác trên tất cả các phần tử của iterable và do đó, không thể áp dụng cho các iterable vô hạn. func phải là một hàm nhận hai phần tử và trả về một giá trị duy nhất. lấy hai phần tử đầu tiên A và B được trả về bởi iterator và tính toán

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
09. Sau đó, nó yêu cầu phần tử thứ ba, C, tính toán
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
10, kết hợp kết quả này với phần tử thứ tư được trả về và tiếp tục cho đến khi hết lần lặp. Nếu iterable hoàn toàn không trả về giá trị nào, thì một ngoại lệ sẽ được đưa ra. Nếu giá trị ban đầu được cung cấp, thì giá trị đó được sử dụng làm điểm bắt đầu và
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
12 là phép tính đầu tiên

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
..      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m:
..     print[key, m[key]]
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
9

Nếu bạn sử dụng with , bạn sẽ thêm tất cả các phần tử của iterable. Trường hợp này phổ biến đến mức có một phần mềm tích hợp đặc biệt được gọi để tính toán trường hợp này

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
0

Tuy nhiên, đối với nhiều cách sử dụng, có thể rõ ràng hơn nếu chỉ viết vòng lặp rõ ràng

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
1

Một chức năng liên quan là. Nó thực hiện phép tính tương tự, nhưng thay vì chỉ trả về kết quả cuối cùng,

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
19 trả về một trình vòng lặp cũng mang lại từng kết quả một phần

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
2

mô-đun điều hành

Mô-đun đã được đề cập trước đó. Nó chứa một tập hợp các hàm tương ứng với các toán tử của Python. Các hàm này thường hữu ích trong mã kiểu chức năng vì chúng giúp bạn không phải viết các hàm tầm thường thực hiện một thao tác đơn lẻ

Một số chức năng trong mô-đun này là

  • phép toán.

    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    21,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    22,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    23,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    24,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    25, …

  • Các phép toán logic.

    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    26,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    27

  • hoạt động bitwise.

    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    28,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    29,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    30

  • so sánh.

    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    31,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    32,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    33,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    34,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    35 và
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    36

  • nhận dạng đối tượng.

    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    37,
    >>> L = [1, 2, 3]
    >>> iterator = iter[L]
    >>> t = tuple[iterator]
    >>> t
    [1, 2, 3]
    
    38

Tham khảo tài liệu của mô-đun người vận hành để biết danh sách đầy đủ

Các chức năng nhỏ và biểu thức lambda

Khi viết các chương trình kiểu hàm, bạn sẽ thường cần các hàm nhỏ hoạt động như các vị từ hoặc kết hợp các phần tử theo một cách nào đó

Nếu có sẵn Python hoặc chức năng mô-đun phù hợp, bạn hoàn toàn không cần xác định chức năng mới

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
3

Nếu chức năng bạn cần không tồn tại, bạn cần viết nó. Một cách để viết các hàm nhỏ là sử dụng biểu thức.

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
39 lấy một số tham số và một biểu thức kết hợp các tham số này, đồng thời tạo một hàm ẩn danh trả về giá trị của biểu thức

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
4

Một cách khác là chỉ sử dụng câu lệnh

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
41 và xác định hàm theo cách thông thường

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
5

Lựa chọn thay thế nào là thích hợp hơn?

Một lý do cho sở thích của tôi là

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
39 khá hạn chế về chức năng mà nó có thể xác định. Kết quả phải có thể tính toán được dưới dạng một biểu thức duy nhất, điều đó có nghĩa là bạn không thể có các phép so sánh
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
44 nhiều chiều hoặc câu lệnh
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
45. Nếu bạn cố gắng làm quá nhiều trong một câu lệnh
>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
39, bạn sẽ nhận được một biểu thức quá phức tạp và khó đọc. Nhanh lên, mã sau đây đang làm gì?

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
6

Bạn có thể tìm ra nó, nhưng phải mất thời gian để gỡ rối biểu thức để tìm ra điều gì đang xảy ra. Sử dụng một câu lệnh ngắn

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
41 lồng nhau làm cho mọi thứ tốt hơn một chút

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
7

Nhưng sẽ là tốt nhất nếu tôi chỉ đơn giản sử dụng một vòng lặp

>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13
1

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
8

Hoặc biểu thức tích hợp và trình tạo

>>> L = [['Italy', 'Rome'], ['France', 'Paris'], ['US', 'Washington DC']]
>>> dict[iter[L]]
{'Italy': 'Rome', 'France': 'Paris', 'US': 'Washington DC'}
9

Nhiều cách dùng của sẽ rõ ràng hơn khi được viết dưới dạng vòng lặp

>>> S = {2, 3, 5, 7, 11, 13}
>>> for i in S:
..     print[i]
2
3
5
7
11
13
1

Fredrik Lundh đã từng đề xuất bộ quy tắc sau để tái cấu trúc việc sử dụng

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
39

  1. Viết một hàm lambda

  2. Viết một bình luận giải thích cái quái gì mà lambda làm

  3. Nghiên cứu bình luận một lúc và nghĩ ra một cái tên nắm bắt được bản chất của bình luận

  4. Chuyển đổi lambda thành câu lệnh def, sử dụng tên đó

  5. Xóa bình luận

Tôi thực sự thích những quy tắc này, nhưng bạn có quyền không đồng ý về việc liệu phong cách không có lambda này có tốt hơn không

Lịch sử sửa đổi và lời cảm ơn

Tác giả xin cảm ơn những người sau đây đã góp ý, sửa chữa và hỗ trợ với các bản thảo khác nhau của bài viết này. Ian Bicking, Nick Coghlan, Nick Efford, Raymond Hettinger, Jim Jewett, Mike Krell, Leandro Lameiro, Jussi Salmela, Collin Winter, Blake Winton

Phiên bản 0. 1. đăng ngày 30 tháng 6 năm 2006

Phiên bản 0. 11. đăng ngày 1 tháng 7 năm 2006. sửa lỗi đánh máy

Phiên bản 0. 2. đăng ngày 10 tháng 7 năm 2006. Đã hợp nhất các phần genexp và listcomp thành một. sửa lỗi đánh máy

Phiên bản 0. 21. Đã thêm nhiều tài liệu tham khảo được đề xuất trong danh sách gửi thư gia sư

Phiên bản 0. 30. Thêm một phần vào mô-đun

>>> L = [1, 2, 3]
>>> iterator = iter[L]
>>> t = tuple[iterator]
>>> t
[1, 2, 3]
53 do Collin Winter viết;

Người giới thiệu

Chung

Cấu trúc và diễn giải các chương trình máy tính, của Harold Abelson và Gerald Jay Sussman với Julie Sussman. Toàn văn tại https. //nhấn nhẹ. mit. edu/sicp/. Trong sách giáo khoa khoa học máy tính cổ điển này, chương 2 và 3 thảo luận về việc sử dụng trình tự và luồng để tổ chức luồng dữ liệu bên trong chương trình. Cuốn sách sử dụng Lược đồ cho các ví dụ của nó, nhưng nhiều cách tiếp cận thiết kế được mô tả trong các chương này có thể áp dụng cho mã Python kiểu chức năng

https. //www. defmacro. org/lan man/fp. html. Giới thiệu chung về lập trình hàm sử dụng các ví dụ Java và có phần giới thiệu lịch sử dài

https. // vi. wikipedia. org/wiki/Functional_programming. Mục Wikipedia chung mô tả lập trình chức năng

https. // vi. wikipedia. org/wiki/Coroutine. Nhập cảnh cho coroutines

https. // vi. wikipedia. org/wiki/Cà ri. Nhập cảnh cho khái niệm cà ri

dành riêng cho Python

https. // nhận biết. cx/TPiP/. Chương đầu tiên của cuốn sách Xử lý văn bản trong Python của David Mertz thảo luận về lập trình hàm để xử lý văn bản, trong phần có tiêu đề “Sử dụng các hàm bậc cao hơn trong xử lý văn bản”

Mertz cũng đã viết một loạt bài gồm 3 phần về lập trình chức năng cho trang DeveloperWorks của IBM;

Python có phải là ngôn ngữ thủ tục không?

Có, Python hỗ trợ cả ngôn ngữ lập trình hướng đối tượng và thủ tục vì đây là ngôn ngữ lập trình cấp cao được thiết kế cho mục đích lập trình chung

Python là khai báo hay mệnh lệnh?

Như đã đề cập trước đó, Python có thể được sử dụng trong cả lập trình mệnh lệnh và khai báo và là một trong những ngôn ngữ phổ biến nhất hiện nay dành cho người mới bắt đầu và các chuyên gia .

Python khai báo so với thủ tục là gì?

Trong ngôn ngữ thủ tục, bạn xác định toàn bộ quá trình và cung cấp các bước để thực hiện. Bạn chỉ cần cung cấp đơn đặt hàng và xác định quy trình sẽ được phục vụ như thế nào. Trong ngôn ngữ khai báo, bạn chỉ cần đặt câu lệnh hoặc mệnh lệnh, và để nó trên hệ thống cách hoàn thành mệnh lệnh đó

Là đối tượng Python

Python được coi là ngôn ngữ lập trình hướng đối tượng hơn là ngôn ngữ lập trình thủ tục. Nó được xác định bằng cách xem các gói Python như Scikit-learn¹, pandas² và NumPy³. Đây là tất cả các gói Python được xây dựng với lập trình hướng đối tượng.

Chủ Đề