Как я могу найти количество аргументов функции Python?

Как я могу найти количество аргументов функции Python? Мне нужно знать, сколько у него нормальных аргументов и сколько именованных аргументов.

Пример:

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

Этот метод имеет 2 аргумента и 1 именованный аргумент.

14 ответов

Решение

Ранее принятый ответ устарел с 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,


Что касается Python 2.x пользователи, в то время как 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 возвращает NamedTuple который содержит аргументы.

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

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

func.__code__.co_argcountдает вам количество любых аргументов ДО *args

func.__kwdefaults__дает вам dict ключевых аргументов ПОСЛЕ *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
someMethod.func_code.co_argcount

или, если текущее имя функции не определено:

import sys

sys._getframe().func_code.co_argcount

inspect.getargspec()

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

Изменено в версии 2.6: Возвращает именованный кортеж ArgSpec(args, varargs, ключевые слова, значения по умолчанию).

См. /questions/9056422/mozhete-li-vyi-perechislit-klyuchevyie-argumentyi-kotoryie-poluchaet-funktsiya.

Помимо вышесказанного, я также видел, что в большинстве случаев функция 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

Вы получаете количество аргументов:

      function.__code__.co_argcount ## 2

И имена или аргументы:

      function.__code__.co_varnames ## ('a', 'b')

Хорошие новости для людей, которые хотят сделать это портативным способом между Python 2 и Python 3.6+: используйте inpsect.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.

Как показывают другие ответы, 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__ строка. Очевидно, что это зависит от формата указанной строки, так что вряд ли является надежным!

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

from inspect import getargspec

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

Это решение для получения количества обязательных аргументов функции (*)

Многие из предложенных здесь решений не работают для этой цели, если используются некоторые более необычные спецификации параметров (параметры только для позиции со значениями по умолчанию, параметры только для ключевых слов без значений по умолчанию и т. д.).

      from typing import Callable, Any
import inspect

def get_mandatory_argcount(f: Callable[..., Any]) -> int:
    """Get the number of mandatory arguments of a function."""
    sig = inspect.signature(f)
    
    def parameter_is_mandatory(p: inspect.Parameter) -> bool:
        return p.default is inspect.Parameter.empty and p.kind not in (
            inspect.Parameter.VAR_POSITIONAL,
            inspect.Parameter.VAR_KEYWORD,
        )
    
    return sum(parameter_is_mandatory(p) for p in sig.parameters.values())

# mandatory keyword-only
def f1(b=2, *args, c, d=1, **kwds): pass
print(get_mandatory_argcount(f1))

# positional only with default
def f2(a=1, /, b=3, *args, **kwargs): pass
print(get_mandatory_argcount(f2))

(*) Я хотел бы поместить это как ответ на Программное определение количества параметров, требуемых функцией - вместо этого Python, но по какой-то причине этот вопрос помечен как дублирующий этот вопрос, несмотря на то, что он конкретно спрашивает о количестве требуемых аргументов, тогда как этот вопрос касается только общего количества аргументов.

В:

import inspect 

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

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

Вне:

4


Примечание. Если бы xyz не находился внутри класса X и не имел "self", а только "a, b, c", то он напечатал бы 3.

Для python ниже 3.5 вы можете заменить inspect.getfullargspec по inspect.getargspec в коде выше.

Предполагая, что вы можете иметь дело с классом на основе methods или просто functions, вы можете сделать что-то вроде следующего.

Это автоматически вычитает один ввод, если ввод является методом класса (и, следовательно, включает self).

      import types
def get_arg_count(fn):
    extra_method_input_count=1 if isinstance(fn, types.MethodType) else 0
    return fn.__code__.co_argcount-extra_method_input_count

Затем вы можете применять по мере необходимости к функциям или методам:

      def fn1(a, b, c):
    return None

class cl1:
    def fn2(self, a, b, c):
        return None

print(get_arg_count(fn1)) #=> 3
print(get_arg_count(cl1().fn2)) #=> 3

Принятый ответ Димитриса Фасаракиса Хиллиард предлагает получить параметры в строковом формате, но я думаю, что при синтаксическом анализе этой строки можно допустить ошибку, и поэтому я скорее создал список параметров, напрямую используя модуль проверки.

      import inspect
def my_function(a,b,c):
    #some code
    pass

result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']
Другие вопросы по тегам