¿Cómo puedo leer la firma de una función, incluidos los valores de argumento predeterminados?

Dado un objeto de función, ¿cómo puedo obtener su firma? Por ejemplo, para:

def myMethod(firt, second, third='something'): pass 

Me gustaría obtener "myMethod(firt, second, third='something')" .

 import inspect def foo(a, b, x='blah'): pass print(inspect.getargspec(foo)) # ArgSpec(args=['a', 'b', 'x'], varargs=None, keywords=None, defaults=('blah',)) 

Sin embargo, tenga en cuenta que inspect.getargspec() está en desuso desde Python 3.0.

Python 3.0–3.4 recomienda inspect.getfullargspec() .

Python inspect.signature() recomienda inspect.signature() .

Podría decirse que la forma más fácil de encontrar la firma para una función sería help(function) :

 >>> def function(arg1, arg2="foo", *args, **kwargs): pass >>> help(function) Help on function function in module __main__: function(arg1, arg2='foo', *args, **kwargs) 

Además, en Python 3 se agregó un método al módulo de inspect llamado signature , que está diseñado para representar la firma de un objeto que se puede llamar y su anotación de retorno :

 >>> from inspect import signature >>> def foo(a, *, b:int, **kwargs): ... pass >>> sig = signature(foo) >>> str(sig) '(a, *, b:int, **kwargs)' >>> str(sig.parameters['b']) 'b:int' >>> sig.parameters['b'].annotation  
 #! /usr/bin/env python import inspect from collections import namedtuple DefaultArgSpec = namedtuple('DefaultArgSpec', 'has_default default_value') def _get_default_arg(args, defaults, arg_index): """ Method that determines if an argument has default value or not, and if yes what is the default value for the argument :param args: array of arguments, eg: ['first_arg', 'second_arg', 'third_arg'] :param defaults: array of default values, eg: (42, 'something') :param arg_index: index of the argument in the argument array for which, this function checks if a default value exists or not. And if default value exists it would return the default value. Example argument: 1 :return: Tuple of whether there is a default or not, and if yes the default value, eg: for index 2 ie for "second_arg" this function returns (True, 42) """ if not defaults: return DefaultArgSpec(False, None) args_with_no_defaults = len(args) - len(defaults) if arg_index < args_with_no_defaults: return DefaultArgSpec(False, None) else: value = defaults[arg_index - args_with_no_defaults] if (type(value) is str): value = '"%s"' % value return DefaultArgSpec(True, value) def get_method_sig(method): """ Given a function, it returns a string that pretty much looks how the function signature would be written in python. :param method: a python method :return: A string similar describing the pythong method signature. eg: "my_method(first_argArg, second_arg=42, third_arg='something')" """ # The return value of ArgSpec is a bit weird, as the list of arguments and # list of defaults are returned in separate array. # eg: ArgSpec(args=['first_arg', 'second_arg', 'third_arg'], # varargs=None, keywords=None, defaults=(42, 'something')) argspec = inspect.getargspec(method) arg_index=0 args = [] # Use the args and defaults array returned by argspec and find out # which arguments has default for arg in argspec.args: default_arg = _get_default_arg(argspec.args, argspec.defaults, arg_index) if default_arg.has_default: args.append("%s=%s" % (arg, default_arg.default_value)) else: args.append(arg) arg_index += 1 return "%s(%s)" % (method.__name__, ", ".join(args)) if __name__ == '__main__': def my_method(first_arg, second_arg=42, third_arg='something'): pass print get_method_sig(my_method) # my_method(first_argArg, second_arg=42, third_arg="something") 

Intenta llamar a la help sobre un objeto para descubrirlo.

 >>> foo = [1, 2, 3] >>> help(foo.append) Help on built-in function append: append(...) L.append(object) -- append object to end 

Tal vez un poco tarde para la fiesta, pero si también desea mantener el orden de los argumentos y sus valores predeterminados , puede usar el módulo de árbol de syntax abstracta (ast) .

Aquí hay una prueba de concepto (tenga cuidado con el código para ordenar los argumentos y hacerlos coincidir con sus valores predeterminados que definitivamente se pueden mejorar / aclarar):

 import ast for class_ in [c for c in module.body if isinstance(c, ast.ClassDef)]: for method in [m for m in class_.body if isinstance(m, ast.FunctionDef)]: args = [] if method.args.args: [args.append([a.col_offset, a.id]) for a in method.args.args] if method.args.defaults: [args.append([a.col_offset, '=' + a.id]) for a in method.args.defaults] sorted_args = sorted(args) for i, p in enumerate(sorted_args): if p[1].startswith('='): sorted_args[i-1][1] += p[1] sorted_args = [k[1] for k in sorted_args if not k[1].startswith('=')] if method.args.vararg: sorted_args.append('*' + method.args.vararg) if method.args.kwarg: sorted_args.append('**' + method.args.kwarg) signature = '(' + ', '.join(sorted_args) + ')' print method.name + signature 

Si todo lo que intentas hacer es imprimir la función, usa pydoc.

 import pydoc def foo(arg1, arg2, *args, **kwargs): '''Some foo fn''' pass >>> print pydoc.render_doc(foo).splitlines()[2] foo(arg1, arg2, *args, **kwargs) 

Si está intentando analizar realmente la firma de la función, use argspec del módulo de inspección. Tenía que hacer eso al validar la función de script de enganche de un usuario en un marco general.

Código de ejemplo:

 import inspect from collections import OrderedDict def get_signature(fn): params = inspect.signature(fn).parameters args = [] kwargs = OrderedDict() for p in params.values(): if p.default is p.empty: args.append(p.name) else: kwargs[p.name] = p.default return args, kwargs def test_sig(): def fn(a, b, c, d=3, e="abc"): pass assert get_signature(fn) == ( ["a", "b", "c"], OrderedDict([("d", 3), ("e", "abc")]) ) 

Use% pdef en la línea de comando (IPython), se imprimirá solo la firma.

por ejemplo, %pdef np.loadtxt

  np.loadtxt(fname, dtype=, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes')