2012-08-06 55 views
11

Trong Python, giả sử tôi có hàm f mà tôi muốn chuyển xung quanh với một số đối số thứ cấp (giả sử đơn giản rằng nó chỉ là đối số đầu tiên vẫn còn biến).Sự khác nhau giữa functools.partial và lambda tương tự?

Sự khác biệt giữa việc thực hiện theo hai cách này (nếu có) là gì?

# Assume secondary_args and secondary_kwargs have been defined 

import functools 

g1 = functools.partial(f, *secondary_args, **secondary_kwargs) 
g2 = lambda x: f(x, *secondary_args, **secondary_kwargs) 

Trong doc page for partial, ví dụ, có trích dẫn này:

partial đối tượng quy định tại các lớp học hoạt động giống như các phương pháp tĩnh và không biến đổi thành phương pháp ghi nhận trong quá dụ thuộc tính nhìn lên.

Phương thức lambda sẽ bị điều này nếu được sử dụng để tạo phương thức lớp từ các đối số được cung cấp cho lớp (hoặc trong hàm dựng hoặc thông qua hàm sau)?

+1

Tôi nghĩ câu hỏi của tôi khá khác so với câu hỏi được liên kết, tuy nhiên câu trả lời hàng đầu cho câu hỏi đó rất kỹ lưỡng và nó cũng trả lời (bằng sự trùng hợp) phần lớn những gì tôi đang tìm kiếm. Tôi sẽ không phàn nàn nếu nó bị đóng. – ely

+0

Tôi đồng ý không trùng lặp, tôi đã mở lại câu hỏi của bạn. Đối với những người khác tham khảo, câu hỏi liên quan là [ở đây] (http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda). – wim

Trả lời

9
  1. Hàm lambda có cùng loại với chức năng chuẩn, vì vậy nó sẽ hoạt động như một phương pháp thể hiện.

  2. Đối tượng partial trong ví dụ của bạn có thể được gọi như thế này:

    g1(x, y, z) 
    

    dẫn đến cuộc gọi này (cú pháp Python không hợp lệ, nhưng bạn sẽ có được ý tưởng):

    f(*secondary_args, x, y, z, **secondary_kwargs) 
    

    Lambda chỉ chấp nhận một đối số duy nhất và sử dụng một thứ tự đối số khác. (Tất nhiên cả những khác biệt có thể được khắc phục - Tôi chỉ trả lời những gì khác biệt giữa hai phiên bản bạn đã đang có.)

  3. Thực hiện của đối tượng partial là nhanh hơn một chút so với thực hiện tương đương lambda.

+0

Bạn đã lược tả đối tượng 'partial' so với' lambda'? – orlp

+2

@nightcracker: Có, không phải bây giờ, nhưng nhiều lần trong quá khứ. Đối tượng 'partial' không tạo đối tượng mã Python, vì vậy nó lưu một khung ngăn xếp Python đầy đủ. –

+0

@Sven Marnach: và những gì chính xác là nhanh hơn, mã tạo, mã gọi điện thoại hoặc cả hai? – orlp

0

Tôi tin rằng điều phương thức lớp chỉ áp dụng cho các hàm được gán trong khi định nghĩa lớp. Các chức năng được gán sau này không được xử lý đặc biệt.

Ngoài ra, tôi cá nhân ủng hộ lambdas vì chúng phổ biến hơn và do đó làm cho mã dễ hiểu hơn.

class Foo(object): 
    def __init__(self, base): 
     self.int = lambda x:int(x, base) 

print Foo(4).int('11') 
+4

'Tôi cá nhân ủng hộ lambdas vì chúng phổ biến hơn và do đó làm cho mã dễ hiểu hơn.” Tôi chưa bao giờ nghe một trong những phát biểu này trước đây. – phant0m

+0

@ phant0m Hầu hết các phát biểu mà tôi đã nghe về Python lambdas đều có từ 'bị hỏng' trong chúng. ;-) –

+0

@Chris functools.partial sạch hơn, nhưng tôi nghĩ lambdas dễ hiểu hơn miễn là bạn không có vấn đề về phạm vi. Đối với một điều, lambdas có nghĩa là bạn không cần phải nhớ thứ tự đối số chính xác mà functools.partial mất. – Antimony

0

Có, lambda sẽ "bị" từ điều này. partial không có vấn đề này bởi vì nó là một đối tượng với các nhà điều hành cuộc gọi quá tải, chứ không phải là một chức năng thực sự.

Nhưng việc sử dụng lambda như thế này trong định nghĩa lớp học chỉ là lạm dụng.

0

partials không chỉ nhanh hơn khoảng 20% ​​so với lambdas tương đương như đã nói nhưng chúng giữ nguyên trực tiếp về chức năng liên quan. Trong khi trong lambdas chức năng đó là 'burried' trong cơ thể chức năng.

=> Nếu bạn chỉ cần giải quyết vấn đề trì hoãn việc đánh giá một hàm cho đến khi tất cả các arg được biết thì sử dụng partials. Bạn sẽ có cách thức nội tâm tốt hơn so với chôn các cuộc gọi vào các chức năng ẩn danh, tức là lambdas.