Python cà ri vs một phần
Đó là quá trình lấy một hàm nhận nhiều đối số và biến nó thành một hàm nhận một đối số và trả về một hàm khác nhận ít đối số hơn. Ví dụ: hãy xem chức năng bên dưới Show
Một phiên bản được chỉnh sửa của chức năng sẽ trông như thế này
hoặc như thế này
Bây giờ 6 trả về một hàm, nhưng 7 trả về số nguyên 8. Bạn có thể lưu trữ chức năng trung gian dưới dạng 9 và gọi nó sau, như 0 và 1Tại sao cà ri?Đây là một cách mà lập trình viên chức năng lưu và chuyển trạng thái. Đây cũng là một cách tuyệt vời để giảm tính toán tốn kém, đặc biệt là khi các hàm được xử lý thuần túy. Đôi khi nó cũng có thể là một lựa chọn phong cách cho các chức năng cà ri. Đối với một người, tôi thích giao diện của 2 hơn nhiều so với 3. (Bên cạnh đó, tôi cực kỳ yêu thích 4 và cực kỳ ghét 5, iykyk. ) Tìm kiếm nhanh trên google sẽ cung cấp cho bạn một số ví dụ về điều này, vì vậy tôi sẽ không dành quá nhiều thời gian cho câu hỏi “tại sao”. Bài viết này thực sự là về “làm thế nào”. Nếu bạn đang tìm kiếm các ví dụ, bạn có thể xem bài đăng này mà tôi tìm thấy trên các trang web liên mạngTôi nên lưu ý ở đây rằng trong một ngôn ngữ mà các hàm là các đối tượng hạng nhất và hỗ trợ các bao đóng (các hàm được định nghĩa bên trong các hàm khác nắm bắt hoặc có quyền truy cập vào các biến cục bộ của hàm kèm theo), chẳng hạn như Python, Haskell, Scheme . , các chức năng được xử lý có thể mạnh mẽ như các phiên bản không được xử lý của chúng, vì có thể xử lý bất kỳ hàm không được xử lý nào và ngược lại. Sau đây là một bằng chứng khá đơn giản về điều này bằng quy nạp Nếu một hàm $f_n$ nhận các đối số $n$ thì bạn có thể biến hàm đó thành một hàm $c_n$ nhận một đối số và trả về một hàm $c_{n-1}$ nhận các đối số $n-1$ và có . Bạn có thể tiếp tục làm điều này cho đến khi bạn đạt đến $c_1$, nhận một đối số và gọi $f_n$ trên các đối số $n$ nhận được bởi $c_{n}, c_{n-1}, \ldots, c_1$, do đó . Dưới đây là một ví dụ về điều đó 3Và tất nhiên, nếu bạn có hàm $c_n$, thì bạn có thể nhận được $f_n$ từ hàm đó bằng cách gọi $c_n$ $n$ lần với các đối số được cung cấp cho $f_n$, như minh họa bên dưới 4Điều này chứng tỏ rằng có một sự tương ứng một đối một giữa các hàm được sắp xếp và các hàm nhận đối số $n$ cho bất kỳ số tự nhiên dương nào $n$ Còn những hàm không có đối số thì sao? . Và các hàm không thuần túy có thể tạo ra các kỳ lân khó phân tích hơn nhiều nên tôi không nói về chúng ở đây Cà ri mọi thứ trong Pythontừ chối trách nhiệm. Làm điều này theo quyết định của riêng bạn và chỉ với các chức năng thuần túy Mặc dù tôi cực kỳ thích xem 6, nhưng tôi cực kỳ ghét định nghĩa của nó. Người ta có thể đơn giản hóa nó để 6nhưng điều đó cũng không có vẻ đặc biệt hấp dẫn. Chỉ có Haskell là một cách viết gọn gàng 7Nhưng nó vẫn làm lu mờ bản chất thực sự của hàm 7, đó là nó cần năm đối số và cộng tất cả chúng lại với nhau, điều này được thể hiện ngắn gọn nhất trong định nghĩa 9Nhưng chờ đã, bây giờ 7 không được cà ri. Mô-đun 9 của Python có một chức năng gọi là 30 cho phép bạn áp dụng một phần các chức năng, như sau 3Mặc dù đây là một cách để lấy tương đương với việc cà ri ra khỏi một chức năng không được cà ri, nhưng theo ý kiến của tôi thì nó hơi dài dòng. Điều gì sẽ xảy ra nếu chúng ta có thể thêm một trình trang trí vào định nghĩa của 7 để làm nổi bật nó? 5Người trang trí cà riBây giờ chúng ta cần đưa ra một số quyết định thiết kế. Python là một ngôn ngữ rất linh hoạt. Người dùng có thể gọi một hàm với các đối số vị trí hoặc từ khóa. Một số đối số là tùy chọn, vì vậy người dùng có thể không bao giờ cung cấp chúng. Ngoài ra, lý do lớn nhất tại sao currying hữu ích là nó cho phép lập trình viên lưu trạng thái khi cần, và đôi khi bạn chỉ muốn gọi một hàm Curried như 32 thay vì 33, vì sau tất cả, bạn đã xác định hàm Curried của mình là 34 với một bộ trang trí . Tôi muốn người trang trí này xử lý tất cả những thứ đó một cách trang nhã và nó thực sự không khó lắmTôi đã quyết định xác định một hàm 35 nhận vào một số nguyên 36 và trả về một trình trang trí xử lý một hàm nhận ít nhất 36 đối số và khi nhiều đối số đó đã được cung cấp, hàm bao bọc sẽ được gọi với tất cả các đối số vị trí và từ khóa. Ví dụ, 7 sẽ được định nghĩa như sau 0Để xem thêm ví dụ về điều này, vui lòng xem doctests của 35 trong repo github với tất cả mã. Và vui lòng đọc toàn bộ chuỗi tài liệuĐang lưu trạng thái và một phần ứng dụngHãy thử thực hiện 35. Chúng tôi muốn một hàm trả về một hàm trang trí, vì vậy nó sẽ giống như thế này 1Nếu 41 được cung cấp ít nhất 36 đối số trong tổng số (đối số vị trí cộng với từ khóa) thì nó chỉ cần gọi 43, nếu không nó sẽ trả về một ứng dụng một phần. một phần ứng dụng là gì? . Nếu nó được cung cấp ít nhất _______136 đối số thì nó sẽ gọi _______143, nếu không nó sẽ trả về một phần tính toán khác. Chúng ta có thể thực hiện hành vi như vậy trong một lớp 46 2Lưu ý rằng phương thức ma thuật 47 trong Python làm cho một đối tượng có thể gọi được, nghĩa là bây giờ chúng ta có thể gọi các đối tượng 46 như thể chúng là các hàm. Bây giờ chúng ta có thể triển khai 35 khá đơn giản 3Chúng ta thực sự có thể đơn giản hóa mã này hơn một chút, vì một đối tượng 46 không có 61 và không có 62 hoạt động giống hệt như bất kỳ đối tượng 46 nào khác. Chúng ta có thể loại bỏ hoàn toàn hàm 41 và có được cách triển khai khá thanh lịch của 35 4Điều này sẽ giúp bạn đánh giá cao những gì đang thực sự xảy ra khi chúng ta đang cà ri. chúng tôi đang lưu trữ trạng thái và truyền nó đi khắp nơi, và đó là lý do tại sao đôi khi nó chính xác như những gì bạn muốn Một định nghĩa chức năng thuần túyNếu bạn xem kỹ đoạn mã trên, bạn sẽ nhận thấy rằng các đối tượng 46 không bao giờ bị thay đổi và cũng chỉ có hai phương thức được gọi trên các đối tượng đó. 67 trong khi khởi tạo chúng và 47 trong khi gọi chúng dưới dạng hàm (trong mã có lẽ sử dụng hàm curried). Có thể loại bỏ hoàn toàn lớp 46 và tái tạo hành vi tương tự với hai hàm 70 và 71 bên trong 72 5Lưu ý rằng 71 có cùng nội dung với 74 và mã soạn sẵn trong 67 đã hoàn toàn biến mất. Việc triển khai 35 này, được gọi là 77 trong repo github, hoàn toàn là chức năng. Tôi vẫn thích triển khai bằng cách sử dụng 46 hơn vì người ta sẽ phải viết ra các lệnh gọi hàm trên giấy để hiểu điều gì đang diễn ra trong quá trình triển khai này, trong khi các kiểu đầu tiên trong lần triển khai đầu tiên có ý nghĩa hơn nhiều và làm nổi bật bản chất thực sự của những gì . e. , chuyển qua các chức năng được áp dụng một phần. Thật vậy, các loại trong triển khai chức năng là một tổ hợp tồi tệ của 79 và chúng hoàn toàn không thông báo cho người đọc, vì vậy tôi đã loại bỏ chúng trong repo github, nhưng các loại trong lần triển khai đầu tiên kể một câu chuyện rất hayBất chấp những thiếu sót về phong cách của việc triển khai chức năng, tôi đưa nó vào đây để đưa ra một điểm rất quan trọng. có thể chuyển trạng thái không chỉ trong các đối tượng mà còn trong các chức năng (chính xác hơn là các bao đóng). Trường hợp cụ thể, chúng ta có thể thay thế đối tượng 46 bằng các hàm xác định nó, vì nó là một đối tượng bất biến (về mặt kỹ thuật, nó là bất biến, nhưng có thể làm cho nó trở nên bất biến trong Python bằng cách xóa phương thức 91 trong 67, và . Điều này cho thấy rằng có lẽ chúng ta chỉ có thể triển khai lại các lớp bằng cách sử dụng các hàm. Đây sẽ là chủ đề của một bài đăng trên blog trong tương lai (tiếp theo?)Sự kết luậnMặc dù Python không mặc định các chức năng của nó (không giống như Haskell), nhưng có một cách rõ ràng, thanh lịch để triển khai chức năng tương tự. Điều này cũng gợi ý rằng các hàm có thể tự lưu và chuyển trạng thái và các lớp chỉ là đường cú pháp cho một số loại hàm nhất định. Cuối cùng, nó phản ánh thực tế rằng phép tính Lambda, một khung trong đó khai báo biến, định nghĩa hàm và ứng dụng là những hành động khả thi duy nhất, đủ để lập mô hình cho tất cả quá trình tính toán Bạn có thể tìm thấy tất cả các mã trong bài đăng này tại đây. Tôi thực sự khuyên bạn nên đọc các tài liệu để hiểu các quyết định thiết kế mà tôi đã đưa ra và tất cả các tính năng mà trình trang trí cà ri cung cấp Là cà ri giống như ứng dụng một phần?Không cần nhiều đối số. Cà ri khác xa với ứng dụng một phần . Tuy nhiên, có thể sử dụng một phần ứng dụng để thực hiện currying. Tuy nhiên, không thể tính một hàm lấy một số đối số ngẫu nhiên (cho đến khi bạn chắc chắn về các đối số).
Phương pháp một phần trong Python là gì?Hàm một phần là gì? . Bạn có thể nghĩ về một hàm bộ phận như một phần mở rộng của một hàm được chỉ định khác. a component of metaprogramming in Python, a concept that refers to a programmer writing code that manipulates code. You can think of a partial function as an extension of another specified function.
Python có cà ri không?Python không có cú pháp rõ ràng cho hàm Currying ; .
Nhập một phần trong Python là gì?Các hàm một phần cho phép chúng ta sửa một số đối số nhất định của hàm và tạo một hàm mới . Thí dụ. từ funcools nhập một phần. |