Wie finde ich die Anzahl der Argumente einer Python-Funktion?

163

Wie finde ich die Anzahl der Argumente einer Python-Funktion? Ich muss wissen, wie viele normale Argumente es hat und wie viele benannte Argumente.

Beispiel:

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

Diese Methode hat 2 Argumente und 1 benanntes Argument.

Georg Schölly
quelle
43
die Frage ist voll gerechtfertigt; Wenn dies nicht der Fall wäre (da Sie immer die Quelle lesen können), gäbe es keine Rechtfertigung für das inspectStandardbibliotheksmodul.
Flow
Viele Sprachen implementieren mindestens eine ungerechtfertigte Funktion. Das inspectModul hat viele andere Funktionen, daher ist es unfair zu sagen, dass das gesamte Modul ungerechtfertigt wäre, wenn eine bestimmte Funktion darin wäre. Darüber hinaus ist leicht zu erkennen, wie diese Funktion schlecht genutzt werden kann. (Siehe stackoverflow.com/questions/741950 ). Das heißt, es ist eine nützliche Funktion, insbesondere zum Schreiben von Dekorateuren und anderen Funktionen, die mit Funktionen arbeiten.
user1612868

Antworten:

130

Die zuvor akzeptierte Antwort ist ab dem Python 3.0. Anstatt zu verwenden inspect.getargspec, sollten Sie sich jetzt für das entscheidenSignature Klasse entscheiden, die sie ersetzt hat.

Das Erstellen einer Signatur für die Funktion ist über die signatureFunktion einfach :

from inspect import signature

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

sig = signature(someMethod)

Jetzt können Sie entweder die Parameter schnell anzeigen, indem Sie strFolgendes eingeben:

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

oder Sie können auch eine Zuordnung von Attributnamen zu Parameterobjekten über erhalten sig.parameters.

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

Darüber hinaus können Sie rufen lenan , sig.parametersum auch die Anzahl der Argumente zu sehen diese Funktion erfordert:

print(len(params))  # 3

Jeder Eintrag in der paramsZuordnung ist tatsächlich ein ParameterObjekt mit weiteren Attributen, die Ihnen das Leben erleichtern. Das Abrufen eines Parameters und das Anzeigen seines Standardwerts können jetzt problemlos durchgeführt werden mit:

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

ähnlich für den Rest der Objekte in parameters.


Python- 2.xBenutzer sind zwar inspect.getargspec nicht veraltet, aber die Sprache wird bald lauten :-). Die SignatureKlasse ist nicht in der 2.xSerie verfügbar und wird es auch nicht sein. Sie müssen also noch mit arbeiten inspect.getargspec.

Wenn Sie für den Übergang zwischen Python 2 und 3 Code haben, der auf der Schnittstelle von getargspecin Python 2 basiert, und der Wechsel zu signaturein 3zu schwierig ist, haben Sie die wertvolle Option, ihn zu verwenden inspect.getfullargspec. Es bietet eine ähnliche Schnittstelle wie getargspec(ein einzelnes aufrufbares Argument), um die Argumente einer Funktion zu erfassen und gleichzeitig einige zusätzliche Fälle zu behandeln, die getargspecdies nicht tun:

from inspect import getfullargspec

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

args = getfullargspec(someMethod)

Wie bei getargspec, getfullargspeckehrt ein , NamedTuplewelche die Argumente enthält.

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})
Dimitris Fasarakis Hilliard
quelle
1
Gern geschehen @ GeorgSchölly. Ich war überrascht, dass eine beliebte Frage wie diese Lösungen bot, die entweder veraltet oder hinterhältig waren (Blick in das co_argcountAttribut)
Dimitris Fasarakis Hilliard
1
getfullargspecist nicht in Python 2.x implementiert, müssen Sie verwendengetargspec
Peter Gibson
getargspecfunktioniert nicht mit eingebauten Funktionen: getargspec(open)gibt TypeError: <built-in function open> is not a Python functionSiehe diese Antwort für einige Ideen ...
starfry
In Ihrem letzten Beispiel print(args)bekommen defaults=(None,)Sie nicht , wenn Sie es tun defaults=None.
Seanny123
Gibt es eine Möglichkeit, die ursprüngliche Parameteranzahl für eine Funktion zu erhalten, die nach der Dekoration dekoriert wurde?
Gulats
117
import inspect
inspect.getargspec(someMethod)

Siehe das Inspektionsmodul

Jochen Ritzel
quelle
5
Im Allgemeinen das, was Sie möchten, aber dies funktioniert nicht für integrierte Funktionen. Der einzige Weg , zu wissen , diese Informationen für builtins zu bekommen , ist sie zu analysieren doc - String, der fugly aber machbar ist.
Cerin
5
Dies ist in Python 3 veraltet: docs.python.org/3/library/inspect.html#inspect.getargspec
Noisecapella
Gibt es eine Lösung, die in Python 3 nicht veraltet ist?
hlin117
1
Wenn Sie dem Link folgen, werden Sie sehen, dass er die Verwendung von inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife
Ich stellte einen weiteren möglichen Ansatz für eingebaute Funktionen , ohne den docstring Parsen hier: stackoverflow.com/questions/48567935/...
Hello World
31
someMethod.func_code.co_argcount

oder wenn der aktuelle Funktionsname unbestimmt ist:

import sys

sys._getframe().func_code.co_argcount
miaoever
quelle
4
@elyase, mach einfach: dir(someMethod)-> 'func_code'; Gehen Sie weiter: dir(someMethod.func_code)-> 'co_argcount'; Mit der integrierten Funktion können Sie dir()die verfügbaren Methoden eines Objekts ermitteln.
@elyase Ich war auch mutig, also fand ich diese docs.python.org/2/library/inspect.html#types-and-members
rodripf
Zur Unterstützung von Python 3:six.get_function_code(someMethod).co_argcount
Noisecapella
8
@noisecapella keine Notwendigkeit für ein Modul eines Drittanbieters, wenn Sie einfach tun könnensome_method.__code__.co_argcount
Vallentin
1
Im Allgemeinen sollten Sie nicht in das Funktionsobjekt spähen, um diese Dinge zu betrachten. co_argcountwird intern während der Auswertung des Codeobjekts verwendet. Ich versuche zu sagen, dass es wirklich keine Garantie dafür gibt, dass sich diese Attribute nicht von einer Version zur anderen ändern.
Dimitris Fasarakis Hilliard
16

inspect.getargspec ()

Ruft die Namen und Standardwerte der Argumente einer Funktion ab. Ein Tupel von vier Dingen wird zurückgegeben: (args, varargs, varkw, default). args ist eine Liste der Argumentnamen (sie kann verschachtelte Listen enthalten). varargs und varkw sind die Namen der Argumente * und ** oder None. Standard ist ein Tupel von Standardargumentwerten oder Keine, wenn keine Standardargumente vorhanden sind. Wenn dieses Tupel n Elemente enthält, entsprechen sie den letzten n in args aufgelisteten Elementen.

In Version 2.6 geändert: Gibt ein benanntes Tupel ArgSpec zurück (Argumente, Variablen, Schlüsselwörter, Standardeinstellungen).

Siehe can-you-Liste-the-Schlüsselwort-Argumente-a-Python-Funktion-empfängt .

gimel
quelle
5

Außerdem habe ich gesehen, dass die Funktion help () meistens wirklich hilft

Zum Beispiel gibt es alle Details zu den Argumenten, die es braucht.

help(<method>)

gibt das unten

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
quelle
Es wäre gut für Leute, einen Kommentar zu hinterlassen, was mit einem Beitrag nicht stimmt, als einfach auf die Minus-Schaltfläche zu klicken.
Venu Murthy
2
helpFunktion zeigt nur, was die Dokumentzeichenfolge sagt. Haben Sie sogar getestet, ob es mit der Funktionsdefinition in der Frage funktioniert?
0xc0de
@ 0xc0de - Hast du es getestet? Weil es tatsächlich funktioniert. help()spuckt mehr als nur die Dokumentzeichenfolge aus - selbst bei undokumentiertem Code wird die Argspec immer noch ausgedruckt und es wird angezeigt, wo der Code definiert wurde. Der Person, die die ursprüngliche Frage gestellt hat, war nicht klar, ob sie eine maschinen- oder menschenfreundliche Antwort benötigte. Wenn es nur menschenfreundlich sein muss, help()ist es vollkommen ausreichend.
ArtOfWarfare
@ArtOfWarfare überhaupt nicht, wie es jetzt würden Sie unabhängig analysieren müssen help()zurückgibt, und versuchen, das finden argsund kwargs.
Vallentin
5

Gute Nachrichten für Leute, die dies auf tragbare Weise zwischen Python 2 und Python 3.6+ tun möchten: Verwenden Sie die inspect.getfullargspec()Methode. Es funktioniert sowohl in Python 2.x als auch in 3.6+

Wie Jim Fasarakis Hilliard und andere betont haben, war es früher so:
1. In Python 2.x: Verwenden Sie inspect.getargspec()
2. In Python 3.x: Verwenden Sie die Signatur, da getargspec()und getfullargspec()waren veraltet.

Mit Python 3.6 (auf vielfachen Wunsch?) Haben sich die Dinge jedoch in Richtung besser geändert:

Auf der Python 3- Dokumentationsseite :

inspect.getfullargspec (func)

In Version 3.6 geändert : Diese Methode wurde zuvor zugunsten von signature()Python 3.5 als veraltet dokumentiert. Diese Entscheidung wurde jedoch rückgängig gemacht, um eine klar unterstützte Standardschnittstelle für Python 2/3-Code aus einer Quelle wiederherzustellen, der von der Legacy- getargspec()API migriert wird .

HAltos
quelle
3

inspect.getargspec (), um Ihre Anforderungen zu erfüllen

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)
Eds_k
quelle
1
Willkommen bei Stack Overflow! Bitte antworten Sie nicht nur mit dem Quellcode. Versuchen Sie, eine schöne Beschreibung der Funktionsweise Ihrer Lösung zu geben. Siehe: Wie schreibe ich eine gute Antwort? . Danke
sɐunıɔ ןɐ qɐp
2

Wie andere Antworten vermuten lassen, getargspecfunktioniert es gut, solange das abgefragte Objekt tatsächlich eine Funktion ist. Es ist nicht für Arbeit Einbau- Funktionen wie open, lenusw., und eine Ausnahme in solchen Fällen werfen:

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

Die folgende Funktion (inspiriert von dieser Antwort ) zeigt eine Problemumgehung. Es gibt die Anzahl der Argumente zurück, die erwartet werden von 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

Die Idee ist, die Funktionsspezifikation aus der __doc__Zeichenfolge heraus zu analysieren . Offensichtlich hängt dies vom Format der Zeichenfolge ab und ist daher kaum robust!

Sternenhimmel
quelle
2

func.__code__.co_argcountgibt Ihnen Anzahl von irgendwelchen Argumenten VOR *args

func.__kwdefaults__gibt Ihnen ein Diktat der Schlüsselwortargumente NACH *args

func.__code__.co_kwonlyargcount entspricht len(func.__kwdefaults__)

func.__defaults__gibt Ihnen die Werte der optionalen Argumente an , die zuvor angezeigt wurden *args

Hier ist die einfache Illustration:

die Illustration

>>> 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
Hzzkygcs
quelle
0

Im:

import inspect 

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

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

Aus:

4


Hinweis: Wenn xyz nicht in Klasse X wäre und kein "Selbst" und nur "a, b, c" hätte, hätte es 3 gedruckt.

Für Python unter 3.5 möchten Sie möglicherweise im obigen Code inspect.getfullargspecdurch ersetzen inspect.getargspec.

Guillaume Chevalier
quelle