2017-01-04 22 views
0

Ich bin daran interessiert, eine allgemeine Möglichkeit zu erhalten, eine Liste von Argumenten und Schlüsselwortargumenten zu erhalten, die von einem aufrufbaren Python-Objekt genommen werden. Dies ist geradlinig für Funktionen mit der inspect.getargspec Funktion, zum Beispiel:Argumente für jedes aufrufbare Objekt erhalten?

import inspect 
from functools import partial 

def foo(*args, **kwargs): 
    return args, kwargs 

print(inspect.getargspec(foo)) 
>>ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None) 

def bar(*args): 
    return args 

print(inspect.getargspec(bar)) 
>>ArgSpec(args=[], varargs='args', keywords=None, defaults=None) 

Dies ist jedoch nicht in Fällen wie diese:

partial_function = partial(foo, kwarg="value") 

inspect.getargspec(partial_function) 
>>TypeError: <functools.partial object at 0x11748bc58> is not a Python function 

class Foo(object): 
    def __call__(self, *args, **kwargs): 
     return args, kwargs 

foo_instance = Foo() 

inspect.getargspec(foo_instance) 
>>TypeError: <__main__.Foo object at 0x116c13ed0> is not a Python function 

inspect.getargspec(zip) 
>>TypeError: <built-in function zip> is not a Python function 

Hinweis, dass es Möglichkeiten gibt, die Argumente zu erhalten, für die Teilfunktion und für das aufrufbare Objekt, das heißt:

inspect.getargspec(partial_function.func) 
>>ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None) 

inspect.getargspec(foo_instance.__call__) 
>>ArgSpec(args=['self'], varargs='args', keywords='kwargs', defaults=None) 

aber ich möchte eine allgemeinere Art und Weise, diese Ergebnisse zu erhalten, wenn überhaupt möglich.

+1

oh warte, verwenden Sie Python 2? –

+0

Ahh ja, ich benutze Python 2. Gut zu wissen, dass Python 3 so große Unterstützung für diese Informationen hat. –

Antwort

2

Alle diese können mithilfe der inspect.signature Helferfunktion behandelt werden, die, wie in seiner docs angegeben:

akzeptiert eine breite Palette von Python Callables, von einfachen Funktionen und Klassen zu functools.partial() Objekte.

Was signature tut, ist es Ihre aufrufbar nimmt und konstruiert ein Signature Objekt von ihm:

>>> from inspect import signature 
>>> s = signature(Foo()) # class as shown in your example 

mit den Argumenten nun im parameters Mapping Attribut liegen für die Signature Beispiel:

>>> s.parameters 
mappingproxy({'args': <Parameter "*args">, 'kwargs': <Parameter "**kwargs">}) 

Mit einem Objekt partial erhalten Sie die entsprechende Darstellung:

>>> def foo(a, b, c): pass 
>>> p = partial(foo, c = 30) 
>>> signature(p).parameters 
<Signature (a, b, *, c=20)> 

Wie für integrierte Funktionen wie zip, ist dies nicht immer möglich ist, setzen einige dieser Funktionen nicht über die entsprechenden Metadaten eine Signatur, from PEP 362 zu konstruieren:

Einige Funktionen können nicht in gewissen Implementierungen von Python introspectable sein. In CPython beispielsweise stellen integrierte Funktionen, die in C definiert sind, keine Metadaten zu ihren Argumenten bereit. Das Hinzufügen von Unterstützung für diese PEP ist nicht möglich.

So, während zip nicht der Typ ist, Informationen über sich selbst zu entlarven, andere sind zB all:

>>> signature(all) 
<Signature (iterable, /)> 

Sie leider eine try-except für diese benötigen werden, gibt es nichts anderes, das sein kann, erledigt.

Die Fälle, dass die signature Helfer-Handles in der implementation section of PEP 362 aufgezählt werden, die es eingeführt.

Im Allgemeinen ist inspect.getargspec seit einiger Zeit in Python 3 veraltet, der vorgeschlagene Ansatz (wenn Sie Python 3 verwenden) besteht darin, die über Signature Objekte angebotene Darstellung zu verwenden.

Wenn auf Python 2, ich bin mir ziemlich sicher, Sie können es nicht direkt mit getargspec tun, sollten Sie getfullargspec als Anttis 'Antwort schlägt vor.

0

getfullargspec behandelt auch Teiltöne korrekt. Es war zuvor veraltet, aber war undefiniert, da es als sehr nützlich für single-source Python 2/3 Polyglot-Code angesehen wurde. Eine andere Option ist signature, die etwas komplizierter ist.

Verwandte Themen