2010-10-22 14 views
12

Tôi đang chơi với Python có thể gọi. Về cơ bản bạn có thể định nghĩa một lớp python và thực hiện phương thức __call__ để làm cho cá thể của lớp này có thể gọi được. ví dụ:Không thể nhận được argspec cho Python callables?

class AwesomeFunction(object): 
    def __call__(self, a, b): 
     return a+b 

Kiểm tra mô đun có hàm getargspec, cung cấp cho bạn đặc tả đối số của hàm. Tuy nhiên, có vẻ như tôi không thể sử dụng nó trên một đối tượng có thể được gọi:

fn = AwesomeFunction() 
import inspect 
inspect.getargspec(fn) 

Thật không may, tôi nhận được một Lỗi Loại:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.6/inspect.py", line 803, in getargspec 
    raise TypeError('arg is not a Python function') 
TypeError: arg is not a Python function 

Tôi nghĩ nó khá đáng tiếc là bạn không thể đối xử với bất kỳ đối tượng có thể được gọi là hàm , trừ khi tôi đang làm điều gì sai ở đây?

+0

Cảm ơn bạn đã nhắc nhở tôi về một trong những phương pháp kỳ diệu ít được sử dụng và hiểu, '__call__' –

Trả lời

6

Nếu bạn cần chức năng này, việc viết chức năng bao bọc sẽ kiểm tra xem liệu fn có thuộc tính __call__ và nếu có, hãy chuyển hàm __call__ của nó sang getargspec.

5

Nếu bạn xem định nghĩa của getargspec trong mã mô-đun inspect trên svn.python.org. Bạn sẽ thấy rằng nó gọi isfunction mà tự nó gọi:

isinstance(object, types.FunctionType) 

Kể từ khi, bạn AwesomeFunction rõ ràng không phải là một thể hiện của types.FunctionType nó không thành công.

Nếu bạn muốn nó để làm việc bạn nên thử cách sau:

inspect.getargspec(fn.__call__) 
+5

Tôi biết nó chờ đợi một loại chức năng. Tôi chỉ than thở thực tế là Python không thiết kế theo cách thống nhất các chức năng và các đối tượng. – EnToutCas

+1

Đó là chủ yếu vì Python không phải là một ngôn ngữ hướng đối tượng thái quá (Java là ví dụ tốt nhất của tôi). Trong Java, nghĩa đen mọi thứ là một đối tượng, đến điểm đơn vị nhỏ nhất của nguồn runnable là một lớp. Trong Python, kể từ khi một mô hình như vậy đã được bỏ qua, có, một vài tính năng bị thiếu, nhưng nó thường rõ ràng hơn. –

+0

@EnToutCas: Viết đề xuất/bản vá. Có thể hoặc là A) được chấp nhận, hoặc B) bị bắn hạ với lý do chứng minh tại sao đó là một ý tưởng tồi. –

0

__call__ định nghĩa cái gì đó có thể được gọi bởi một cá thể của lớp. Bạn không cho hàm getargspec hợp lệ vì bạn đang chuyển một cá thể lớp cho nó.

Sự khác biệt giữa __init__call__ là thế này:

fn = AwesomeFunction() # call to __init__ 
fn(1, 2) # call to __call__ 
Các vấn đề liên quan