Làm cách nào tôi có thể tìm thấy số lượng đối số của hàm Python?


163

Làm cách nào tôi có thể tìm thấy số lượng đối số của hàm Python? Tôi cần biết nó có bao nhiêu đối số bình thường và có bao nhiêu đối số được đặt tên.

Thí dụ:

def someMethod(self, arg1, kwarg1=None):
    pass

Phương thức này có 2 đối số và 1 đối số có tên.


43
Câu hỏi được bảo hành đầy đủ; nếu không phải (vì bạn luôn có thể đọc nguồn), sẽ không có bất kỳ lời biện minh nào cho inspectmô-đun thư viện chuẩn.
chảy

Rất nhiều ngôn ngữ thực hiện ít nhất một tính năng không chính đáng. Các inspectmô-đun có rất nhiều tính năng khác, vì vậy nó là không công bằng để nói rằng toàn bộ mô-đun sẽ được phi lý nếu một chức năng cụ thể trong đó là gì. Hơn nữa, thật dễ dàng để thấy tính năng này có thể được sử dụng kém như thế nào. (Xem stackoverflow.com/questions/741950 ). Điều đó nói rằng, nó là một tính năng hữu ích, đặc biệt là để viết trang trí và các chức năng khác hoạt động trên chức năng.
dùng1612868

Câu trả lời:


130

Câu trả lời được chấp nhận trước đó đã được phản đối tính Python 3.0. Thay vì sử dụng, inspect.getargspecbây giờ bạn nên chọn Signaturelớp thay thế nó.

Tạo chữ ký cho chức năng thật dễ dàng thông qua signaturechức năng :

from inspect import signature

def someMethod(self, arg1, kwarg1=None):
    pass

sig = signature(someMethod)

Bây giờ, bạn có thể xem các tham số của nó một cách nhanh chóng bằng cách nhập strnó:

str(sig)  # returns: '(self, arg1, kwarg1=None)'

hoặc bạn cũng có thể có được ánh xạ tên thuộc tính đến các đối tượng tham số thông qua sig.parameters.

params = sig.parameters 
print(params['kwarg1']) # prints: kwarg1=20

Ngoài ra, bạn có thể gọi lenvề sig.parameterscũng để xem số lượng các đối số chức năng này đòi hỏi:

print(len(params))  # 3

Mỗi mục trong paramsánh xạ thực sự là một Parameterđối tượng có thêm các thuộc tính làm cho cuộc sống của bạn dễ dàng hơn. Ví dụ: lấy một tham số và xem giá trị mặc định của nó giờ đây được thực hiện dễ dàng với:

kwarg1 = params['kwarg1']
kwarg1.default # returns: None

tương tự cho phần còn lại của các đối tượng chứa trong parameters.


Đối với 2.xngười dùng Python , mặc dù inspect.getargspec không bị phản đối, ngôn ngữ sẽ sớm là :-). Các Signaturelớp học không có sẵn trong các 2.xloạt và sẽ không được. Vì vậy, bạn vẫn cần phải làm việc với inspect.getargspec.

Đối với việc chuyển đổi giữa Python 2 và 3, nếu bạn có mã dựa trên giao diện của getargspecPython 2 và việc chuyển sang signaturein 3quá khó khăn, bạn có tùy chọn sử dụng có giá trịinspect.getfullargspec . Nó cung cấp một giao diện tương tự getargspec(một đối số có thể gọi được) để lấy các đối số của hàm đồng thời xử lý một số trường hợp bổ sung getargspeckhông:

from inspect import getfullargspec

def someMethod(self, arg1, kwarg1=None):
    pass

args = getfullargspec(someMethod)

Như với getargspec, getfullargspectrả về một NamedTupletrong đó có chứa các đối số.

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})

1
Bạn được chào đón @ GeorgSchölly. Tôi đã ngạc nhiên khi một câu hỏi phổ biến như câu hỏi này đưa ra các giải pháp bị từ chối hoặc lén lút phải (nhìn trộm trong co_argcountthuộc tính.)
Dimitris Fasarakis Hilliard

1
getfullargspeckhông được triển khai trong Python 2.x, bạn cần sử dụnggetargspec
Peter Gibson

getargspeckhông hoạt động trên các chức năng tích hợp: getargspec(open)đưa ra TypeError: <built-in function open> is not a Python functionXem câu trả lời này cho một số ý tưởng ...
starfry

Trong ví dụ cuối cùng của bạn, khi bạn print(args)không nhận được defaults=(None,)bạn nhận được defaults=None.
Seanny123

Có cách nào để lấy số tham số ban đầu cho một chức năng đã được trang trí đăng trang trí ..?
Gulats

117
import inspect
inspect.getargspec(someMethod)

xem mô-đun kiểm tra


5
Nói chung những gì bạn muốn, nhưng điều này không hoạt động cho các chức năng tích hợp. Cách duy nhất để biết để có được thông tin này cho các nội trang là phân tích chuỗi doc của chúng , có thể chạy được nhưng có thể thực hiện được.
Cerin

5
Này không được chấp bằng Python 3: docs.python.org/3/library/inspect.html#inspect.getargspec
noisecapella

Có giải pháp nào không được dùng trong Python 3 không?
hlin117

1
Nếu bạn làm theo các liên kết mà bạn sẽ thấy rằng nó khuyến cáo sử dụng inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife

Tôi đã đăng một cách tiếp cận khả thi khác cho các hàm dựng sẵn mà không cần phân tích chuỗi doc tại đây: stackoverflow.com/questions/48567935/ mẹo
HelloWorld

31
someMethod.func_code.co_argcount

hoặc, nếu tên hàm hiện tại không xác định:

import sys

sys._getframe().func_code.co_argcount

4
@elyase, chỉ cần làm: dir(someMethod)-> 'func_code'; Đi xa hơn: dir(someMethod.func_code)-> 'co_argcount'; Bạn có thể sử dụng tích hợp dir()để xác định các phương thức có sẵn của một đối tượng.

@elyase Tôi đã courious quá, vì vậy tôi thấy điều này docs.python.org/2/library/inspect.html#types-and-members
rodripf

Để hỗ trợ Python 3:six.get_function_code(someMethod).co_argcount
noisecapella 8/2/2016

8
@noisecapella không cần mô-đun của bên thứ ba, khi bạn có thể làm một cách đơn giảnsome_method.__code__.co_argcount
vallentin

1
Nói chung, bạn không nên nhìn trộm bên trong đối tượng chức năng để xem xét những điều này. co_argcountđược sử dụng nội bộ trong quá trình đánh giá đối tượng mã. Điều tôi đang cố gắng nói là, thực sự không có gì đảm bảo rằng các thuộc tính này sẽ không thay đổi từ bản phát hành này sang bản phát hành khác.
Dimitris Fasarakis Hilliard

16

Kiểm tra.getargspec ()

Lấy tên và giá trị mặc định của các đối số của hàm. Một bộ bốn điều được trả về: (args, varargs, varkw, default). args là một danh sách các tên đối số (nó có thể chứa các danh sách lồng nhau). varargs và varkw là tên của các đối số * và ** hoặc Không có. mặc định là một bộ các giá trị đối số mặc định hoặc Không có nếu không có đối số mặc định; nếu bộ dữ liệu này có n phần tử, chúng tương ứng với n phần tử cuối cùng được liệt kê trong args.

Đã thay đổi trong phiên bản 2.6: Trả về một tuple ArgSpec có tên (args, varargs, Keywords, default).

Xem can-you-list-the-keyword-argument-a-python-function-receive .


5

Thêm vào ở trên, tôi cũng đã thấy rằng hầu hết các hàm help () thực sự có ích

Ví dụ, nó cung cấp cho tất cả các chi tiết về các đối số cần có.

help(<method>)

đưa ra dưới đây

method(self, **kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.

Args:
  date: string, Represents the date in yyyy-mm-dd format for which the data is to be fetched. (required)
  pageToken: string, Token to specify next page.
  parameters: string, Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.

Returns:
  An object of the form:

    { # JSON template for a collection of usage reports.
    "nextPageToken": "A String", # Token for retrieving the next page
    "kind": "admin#reports#usageReports", # Th

Sẽ tốt hơn nếu mọi người để lại nhận xét về những gì sai với bài đăng hơn là chỉ nhấp vào nút trừ.
Venu Murthy

2
helpchức năng chỉ hiển thị những gì các chuỗi nói. Bạn thậm chí đã kiểm tra nếu nó hoạt động với định nghĩa hàm trong câu hỏi?
0xc0de

@ 0xc0de - Bạn đã thử chưa? Bởi vì nó thực sự hoạt động. help()phun ra nhiều hơn chỉ là chuỗi doc - ngay cả trên mã không có giấy tờ, nó vẫn in ra argspec và cho bạn biết mã được xác định ở đâu. Người đăng câu hỏi ban đầu không rõ liệu họ cần câu trả lời thân thiện với máy móc hay con người. Nếu nó chỉ cần thân thiện với con người, help()là hoàn toàn đầy đủ.
ArtOfWarfare 17/1/2016

@ArtOfWarfare hoàn toàn không, vì bây giờ bạn sẽ phải phân tích bất cứ điều gì help()trả về, và thử và tìm argskwargs.
vallentin

5

Tin vui cho những người muốn thực hiện việc này theo cách di động giữa Python 2 và Python 3.6+: inspect.getfullargspec()phương thức sử dụng . Nó hoạt động trong cả Python 2.x và 3.6+

Như Jim Fasarakis Hilliard và những người khác đã chỉ ra, nó đã từng như thế này:
1. Trong Python 2.x: use inspect.getargspec()
2. Trong Python 3.x: sử dụng chữ ký, như getargspec()getfullargspec()không được dùng nữa.

Tuy nhiên, bắt đầu Python 3.6 (theo nhu cầu phổ biến?), Mọi thứ đã thay đổi theo hướng tốt hơn:

Từ trang tài liệu Python 3 :

Kiểm tra.getfullargspec (func)

Đã thay đổi trong phiên bản 3.6 : Phương pháp này trước đây được ghi nhận là không dùng trong signature()Python 3.5, nhưng quyết định đó đã bị đảo ngược để khôi phục giao diện tiêu chuẩn được hỗ trợ rõ ràng cho mã Python 2/3 nguồn đơn di chuyển khỏi getargspec()API kế thừa .


3

Kiểm tra.getargspec () để đáp ứng nhu cầu của bạn

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)

1
Chào mừng bạn đến với Stack Overflow! Xin đừng trả lời chỉ với mã nguồn. Cố gắng cung cấp một mô tả hay về cách giải pháp của bạn hoạt động. Xem: Làm thế nào để tôi viết một câu trả lời tốt? . Cảm ơn
sunıɔ qɐp

2

Như các câu trả lời khác cho thấy, getargspechoạt động tốt miễn là điều được truy vấn thực sự là một chức năng. Nó không làm việc cho tích hợp các chức năng như open, len, vv, và sẽ ném một ngoại lệ trong trường hợp này:

TypeError: <built-in function open> is not a Python function

Hàm dưới đây (lấy cảm hứng từ câu trả lời này ) thể hiện một cách giải quyết. Nó trả về số lượng đối số dự kiến ​​bởi f:

from inspect import isfunction, getargspec
def num_args(f):
  if isfunction(f):
    return len(getargspec(f).args)
  else:
    spec = f.__doc__.split('\n')[0]
    args = spec[spec.find('(')+1:spec.find(')')]
    return args.count(',')+1 if args else 0

Ý tưởng là phân tích hàm spec ra khỏi __doc__chuỗi. Rõ ràng điều này phụ thuộc vào định dạng của chuỗi đã nói nên hầu như không mạnh mẽ!


2

func.__code__.co_argcountcung cấp cho bạn số lượng của bất kỳ đối số TRƯỚC *args

func.__kwdefaults__cung cấp cho bạn một lệnh của các đối số từ khóa SAU *args

func.__code__.co_kwonlyargcount bằng len(func.__kwdefaults__)

func.__defaults__cung cấp cho bạn các giá trị của các đối số tùy chọn xuất hiện trước đó *args

Dưới đây là minh họa đơn giản:

hình minh họa

>>> def a(b, c, d, e, f=1, g=3, h=None, *i, j=2, k=3, **L):
    pass

>>> a.__code__.co_argcount
7
>>> a.__defaults__
(1, 3, None)
>>> len(a.__defaults__)
3
>>> 
>>> 
>>> a.__kwdefaults__
{'j': 2, 'k': 3}
>>> len(a.__kwdefaults__)
2
>>> a.__code__.co_kwonlyargcount
2

0

Trong:

import inspect 

class X:
    def xyz(self, a, b, c): 
        return 

print(len(inspect.getfullargspec(X.xyz).args))

Ngoài:

4


Lưu ý: Nếu xyz không ở trong lớp X và không có "tự" và chỉ "a, b, c", thì nó sẽ được in 3.

Đối với python dưới 3,5, bạn có thể muốn thay thế inspect.getfullargspecbằng inspect.getargspecmã ở trên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.