Як я можу знайти кількість аргументів функції Python?


163

Як я можу знайти кількість аргументів функції Python? Мені потрібно знати, скільки нормальних аргументів має і скільки названих аргументів.

Приклад:

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

У цього методу є 2 аргументи та 1 названий аргумент.


43
питання повністю виправдане; якби це не було (оскільки ви завжди можете прочитати джерело), ​​для inspectстандартного модуля бібліотеки не було б ніякого виправдання .
течія

Багато мов реалізують хоча б одну невиправдану особливість. inspectМодуль має багато інших функцій, так що це несправедливо сказати , що весь модуль буде невиправданим , якщо одна конкретна функція в ньому була. Більше того, легко зрозуміти, як цю функцію можна було б погано використовувати. (Див. Stackoverflow.com/questions/741950 ). Однак, це корисна функція, особливо для написання декораторів та інших функцій, які працюють над функцією.
користувач1612868

Відповіді:


131

Раніше прийнята відповідь застаріла станом на Python 3.0. Замість використання inspect.getargspecви тепер повинні вибрати Signatureклас, який його замінив.

Створити підпис для функції легко за допомогою signatureфункції :

from inspect import signature

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

sig = signature(someMethod)

Тепер ви можете швидко переглянути його параметри, strвідвідавши його:

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

або ви також можете отримати відображення імен атрибутів до об'єктів параметрів через sig.parameters.

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

Крім того, ви можете зателефонувати lenна sig.parametersтакож побачити кількість аргументів цієї функції необхідно:

print(len(params))  # 3

Кожен запис у paramsвідображенні насправді є Parameterоб’єктом, який має додаткові атрибути, що полегшують ваше життя. Наприклад, захоплення параметра та перегляд його значення за замовчуванням тепер легко виконується за допомогою:

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

аналогічно для решти об'єктів, що містяться в parameters.


Що стосується 2.xкористувачів Python , поки inspect.getargspec мова не застаріла, мова скоро буде :-). SignatureКлас не доступний в 2.xсерії , і не буде. Тож вам ще потрібно працювати inspect.getargspec.

Що стосується переходу між Python 2 і 3, якщо у вас є код , який спирається на інтерфейс getargspecв Python 2 і перехід до signatureв 3занадто складно, у вас є цінний варіант використання inspect.getfullargspec. Він пропонує аналог інтерфейсу getargspec(єдиний аргумент, що викликається), щоб захопити аргументи функції, а також обробляти деякі додаткові випадки, які getargspecне:

from inspect import getfullargspec

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

args = getfullargspec(someMethod)

Як і у випадку getargspec, getfullargspecповертає a, NamedTupleщо містить аргументи.

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

1
Ласкаво просимо @ GeorgSchölly. Мене здивувало таке популярне питання, як таке, що пропонувало рішення, які або були застарілими, або вниз праворуч підлий (визираючи в co_argcountатрибут.)
Димитріс Фасаракіс Хілліард

1
getfullargspecне реалізовано в Python 2.x, вам потрібно скористатисяgetargspec
Пітер Гібсон

getargspecне працює над вбудованими функціями: getargspec(open)дає TypeError: <built-in function open> is not a Python functionДив. цю відповідь на деякі ідеї ...
starfry

У вашому останньому прикладі, коли print(args)ви цього не отримуєте, defaults=(None,)ви отримуєте defaults=None.
Seanny123

Сі існує спосіб отримати початковий підрахунок параметрів для функції, яка була оформлена після прикраси ..?
Гулат

117
import inspect
inspect.getargspec(someMethod)

див . модуль перевірки


5
Зазвичай те, що ви хочете, але це не працює для вбудованих функцій. Єдиний спосіб дізнатися, як отримати цю інформацію для вбудованих файлів, - це проаналізувати їх докторський рядок, який є неправдивим, але виконаним.
Серін


Чи є рішення, яке не застаріло в Python 3?
hlin117

1
Якщо ви перейдете за посиланням, ви побачите, що він рекомендує використовувати inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife

Тут я розмістив ще один можливий підхід для вбудованих функцій без розбору docstring: stackoverflow.com/questions/48567935/…
HelloWorld

31
someMethod.func_code.co_argcount

або, якщо поточна назва функції не визначена:

import sys

sys._getframe().func_code.co_argcount

4
@elyase, просто роби: dir(someMethod)-> 'func_code'; Ідіть далі: dir(someMethod.func_code)-> 'co_argcount'; Ви можете використовувати вбудований dir()для визначення доступних методів об’єкта.

@elyase Я теж був люб'язний, тому я знайшов це docs.python.org/2/library/inspect.html#types-and-members
rodripf

Для підтримки Python 3:six.get_function_code(someMethod).co_argcount
noisecapella

8
@noisecapella немає необхідності в сторонній модуль, коли можна просто зробитиsome_method.__code__.co_argcount
va Valentin

1
Взагалі, ви не повинні зазирнути всередину функціонального об'єкта, щоб переглянути ці речі. co_argcountвикористовується внутрішньо під час оцінки об'єкта коду. Я намагаюся сказати, що насправді немає гарантій, що ці атрибути не змінюватимуться від одного випуску до іншого.
Dimitris Fasarakis Hilliard

16

inspect.getargspec ()

Отримати імена та значення за замовчуванням аргументів функції. Повертається кортеж із чотирьох речей: (args, varargs, varkw, default). args - це список назв аргументів (він може містити вкладені списки). varargs і varkw - це назви аргументів * і ** або None. defaults - це набір значень аргументів за замовчуванням або None, якщо немає аргументів за замовчуванням; якщо цей кортеж має n елементів, вони відповідають останнім n елементам, переліченим у arg.

Змінено у версії 2.6: повертає названий кортеж ArgSpec (arg, varargs, ключові слова, параметри за замовчуванням).

Дивіться can-you-list-the-Keyword-argument-a-python-function-получены .


5

Додаючи до сказаного, я також бачив, що більшість разів функція help () справді допомагає

Наприклад, він містить усі подробиці щодо аргументів, які він приймає.

help(<method>)

наведено нижче

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

Людям було б добре залишити коментар щодо того, що не так у публікації, ніж просто натискати на кнопку мінус.
Venu Murthy

2
helpФункція показує лише те, що говорить docstring. Ви навіть тестували, чи працює це з визначенням функції у питанні?
0xc0de

@ 0xc0de - Ви протестували? Тому що це насправді працює. help()випльовує більше, ніж просто docstring - навіть за недокументованим кодом він все одно виводить argspec та повідомляє, де був визначений код. Людині, яка розмістила оригінальне запитання, не було зрозуміло, чи потрібна їм відповідь, яка була машинною чи доброзичливою для людини. Якщо потрібно лише бути доброзичливим до людини, help()це цілком адекватно.
ArtOfWarfare

@ArtOfWarfare зовсім не так, як зараз вам доведеться проаналізувати те, що help()повертається, і спробувати знайти argsі kwargs.
валентін

5

Хороша новина для людей, які хочуть зробити це портативно між Python 2 та Python 3.6+: використовувати inspect.getfullargspec()метод. Він працює як у Python 2.x, так і в 3.6+

Як вказували Джим Фасаракіс Хілліард та інші, це було так:
1. У Python 2.x: використовуйте inspect.getargspec()
2. У Python 3.x: використовуйте підпис, як getargspec()і getfullargspec()застаріли.

Однак, починаючи з Python 3.6 (за популярним попитом?), Справи змінилися на краще:

На сторінці документації Python 3 :

inspect.getfullargspec (func)

Змінено у версії 3.6 : Раніше цей метод був задокументований як застарілий на користь signature()в Python 3.5, але це рішення було відмінено для відновлення чітко підтримуваного стандартного інтерфейсу для однопотокового коду Python 2/3, який мігрує від застарілого getargspec()API.


3

inspect.getargspec () для задоволення ваших потреб

from inspect import getargspec

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

1
Ласкаво просимо до переповнення стека! Не відповідайте лише вихідним кодом. Спробуйте надати приємний опис про те, як працює ваше рішення. Дивіться: Як написати гарну відповідь? . Спасибі
sɐunıɔ ןɐ qɐp

2

Як підказують інші відповіді, getargspecпрацює добре, поки запитувана річ насправді є функцією. Він не працює для вбудованих функцій, таких як open, lenі т. Д., І викине виняток у таких випадках:

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

Наведена нижче функція (натхненна цією відповіддю ) демонструє рішення. Він повертає кількість очікуваних аргументів 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

Ідея полягає в аналізі специфікації функції з __doc__рядка. Очевидно, це спирається на формат згаданого рядка, тому навряд чи надійний!


2

func.__code__.co_argcountдає вам кількість будь-яких аргументів перед *args

func.__kwdefaults__дає висновок про аргументи ключових слів ПІСЛЯ *args

func.__code__.co_kwonlyargcount дорівнює len(func.__kwdefaults__)

func.__defaults__дає значення необов'язкових аргументів, які з’являються раніше *args

Ось проста ілюстрація:

ілюстрації

>>> 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

В:

import inspect 

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

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

Вийшов:

4


Примітка: Якби xyz не був у класі X і не мав "Я", а просто "a, b, c", він би надрукував 3.

Для python нижче 3,5, ви можете замінити inspect.getfullargspecйого inspect.getargspecв наведеному вище коді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.