2009-09-23 56 views
6

đây là từ mã nguồn của csv2rec trong matplotlibMã chức năng python này hoạt động như thế nào?

cách chức năng này hoạt động, nếu thông số duy nhất của nó là 'func, mặc định'?

def with_default_value(func, default): 
    def newfunc(name, val): 
     if ismissing(name, val): 
      return default 
     else: 
      return func(val) 
    return newfunc 

ismissing lấy tên và giá trị và xác định xem hàng có được che trong một mảng không.

func sẽ là str, int, float hoặc dateparser ... nó chuyển đổi dữ liệu. Có lẽ không quan trọng. Tôi chỉ tự hỏi làm cách nào để có thể nhận được 'tên' và 'giá trị'

Tôi là người mới bắt đầu. Cảm ơn bất kỳ 2cents! Tôi hy vọng sẽ có đủ tốt để giúp đỡ người khác!

+1

không nên có một khoảng trống như "if ismissing"? – recursive

Trả lời

8

này with_default_value chức năng là những gì thường được gọi (không chính xác) như "đóng cửa" (về mặt kỹ thuật, việc đóng cửa là đúng hơn là nội chức năng đó được trở lại, đây newfunc - xem ví dụ here). Thông thường hơn, with_default_value là hàm số thứ tự cao hơn ("HOF"): có chức năng (func) làm đối số, nó cũng trả về hàm (newfunc).

Tôi đã nhìn thấy câu trả lời khó hiểu này với trang trí khái niệm và xây dựng bằng Python, mà chắc chắn không là trường hợp - đặc biệt là kể từ khi bạn đề cập đến func thường xuyên là một built-in như int. Trang trí cũng là các chức năng bậc cao hơn, nhưng thay vào đó là các chức năng cụ thể: các chức năng trả về trang trí, tức là"được làm giàu", phiên bản của đối số chức năng của chúng (chỉ là đối số chỉ đối số - "trang trí với đối số" được lấy thông qua một cấp độ khác của hàm/đóng cửa lồng nhau, không bằng cách cho trang trí HOF nhiều hơn một đối số) , được gán lại chính xác cùng tên với đối số chức năng đó (và vì vậy thường có cùng chữ ký - bằng cách sử dụng một trình trang trí khác sẽ là cực kỳ riêng, không phải là thành ngữ, không đọc được, v.v ...).

Vì vậy, hãy quên trang trí, hoàn toàn không liên quan gì đến vụ án và tập trung vào việc đóng cửa newfunc. Hàm song song có thể tham chiếu đến (mặc dù không rebind) tất cả các tên biến cục bộ (bao gồm tên đối số, vì đối số là biến cục bộ) của (các) hàm kèm theo - đó là lý do tại sao nó được gọi là đóng: "biến miễn phí". Tại đây, newfunc có thể tham chiếu đến funcdefault - và thực hiện.

Hàm bậc cao là một điều rất tự nhiên trong Python, đặc biệt vì hàm là đối tượng hạng nhất (vì vậy không có gì đặc biệt bạn cần làm để chuyển chúng làm đối số, trả về dưới dạng giá trị hàm hoặc thậm chí lưu trữ chúng trong danh sách hoặc các vùng chứa khác, vv) và không có sự khác biệt về không gian tên giữa các hàm và các loại đối tượng khác, không có chức năng gọi tự động bởi vì chúng được đề cập, v.v. (Khó hơn - khó hơn một chút, hoặc khó khăn hơn, tùy theo - bằng các ngôn ngữ khác vẽ nhiều sự phân biệt của loại này). Trong Python, đề cập đến một hàm chỉ là - một đề cập; CALL chỉ xảy ra nếu và khi đối tượng hàm (được gọi theo tên, hoặc theo cách khác) được theo sau bởi dấu ngoặc đơn.

Đó là tất cả về ví dụ này - vui lòng chỉnh sửa câu hỏi của bạn, nhận xét tại đây, v.v. nếu có một số khía cạnh cụ thể khác mà bạn vẫn còn nghi ngờ!

Chỉnh sửa: vì vậy, OP nhận xét lịch sự yêu cầu thêm ví dụ về "nhà máy đóng cửa". Dưới đây là một - tưởng tượng một số loại trừu tượng của GUI toolkit, và bạn đang cố gắng để làm:

for i in range(len(buttons)): 
    buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i)) 

nhưng điều này không làm việc đúng - i trong lambda là muộn-ràng buộc, như vậy theo thời gian một nút được nhấp vào Giá trị i luôn là chỉ số của nút cuối cùng, bất kể nút nào được nhấp vào. Có những giải pháp khả thi khác nhau, nhưng một nhà máy đóng cửa là một khả năng thanh lịch:

def makeOnclick(message): 
    return lambda: mainwin.settitle(message) 

for i in range(len(buttons)): 
    buttons[i].onclick(makeOnClick("button %d click!" % i)) 

Ở đây, chúng ta đang sử dụng các nhà máy đóng cửa để tinh chỉnh thời gian ràng buộc của các biến -) Trong một hình thức cụ thể này hay cách khác, đây là một trường hợp sử dụng khá phổ biến cho các nhà máy đóng cửa.

+0

Tôi đoán là tôi đã sửa chữa. Cảm ơn vì đã phân biệt. HOF này có thể được gọi như thế nào? – dcrosta

+0

@dcrosta, tôi không có tên chính thức cho thành ngữ này - giống như hầu hết các HOF quay trở lại đóng cửa, tôi chỉ nghĩ về nó như là một cách thuận tiện để thực hiện một nhà máy chức năng. –

+0

câu trả lời tuyệt vời, đó là một trận chiến, đầu tiên tôi nghĩ rằng anh chàng kia đã có nó, và sau đó bạn đi vào cho touchdown! Cảm ơn tôi nghĩ rằng tất cả chúng ta đã học được điều gì đó! Tôi đã tự hỏi nếu bạn có bất kỳ ví dụ khác về điều này? Chỉ tò mò thôi. Không phải lo lắng nếu nó quá khó để tìm thấy một/làm cho một. – Pete

0

Đây là hàm trả về một hàm khác. namevalue là các tham số của hàm trả về.

6

Đây là trình trang trí Python - về cơ bản là trình bao bọc chức năng. (Đọc tất cả về trang trí trong PEP 318 - http://www.python.org/dev/peps/pep-0318/)

Nếu bạn xem xét thông qua mã này, bạn sẽ có thể tìm thấy một cái gì đó như thế này:

def some_func(name, val): 
    # ... 
some_func = with_default_value(some_func, 'the_default_value') 

Mục đích của trang trí này dường như cung cấp một giá trị mặc định nếu hoặc tên hoặc đối số val bị thiếu (có lẽ, nếu chúng được đặt thành Không).

+0

Chính xác, ngoại trừ mã mới thường sẽ trông giống như: @with_default_value (some_func, 'the_default_value') def some_func (tên, val): # ... –

+0

Tôi nghĩ rằng nếu bạn sử dụng cú pháp @ (trước chức năng định nghĩa), bạn phải có một nhà máy trang trí (trong khi đây là một deorator tinh khiết - 2 cấp độ sâu). Nhà máy trang trí có thể chấp nhận các đối số, nhưng không cần. Trừ khi điều này đã thay đổi trong 3.x – dcrosta

+0

@dcrosta: Tôi không nghĩ vậy. Tôi đã sử dụng cả hai cú pháp với trang trí thay thế cho nhau mà không bị ảnh hưởng xấu trong 2.X – priestc

1

Đối với lý do tại sao nó hoạt động:

with_default_value trả về một đối tượng chức năng, mà về cơ bản sẽ là một bản sao đó newfunc lồng nhau, với 'func' gọi và giá trị mặc định substited với bất cứ điều gì đã được thông qua để with_default_value.

Nếu ai đó làm 'foo = with_default_value (quầy bar, 3), giá trị trả về là về cơ bản sẽ là một chức năng mới:

def foo(name, val): 
    ifismissing(name, val): 
     return 3 
    else: 
     return bar(val) 

vì vậy bạn sau đó có thể đi mà giá trị trả về, và gọi nó.

Các vấn đề liên quan