假设函数a_method的定义如下

def a_method(arg1, arg2):
    pass

从a_method本身开始,我怎么能得到参数名-例如,作为字符串的元组,如("arg1", "arg2")?


当前回答

这里有一些东西,我认为会为你想要的工作,使用装饰。

class LogWrappedFunction(object):
    def __init__(self, function):
        self.function = function

    def logAndCall(self, *arguments, **namedArguments):
        print "Calling %s with arguments %s and named arguments %s" %\
                      (self.function.func_name, arguments, namedArguments)
        self.function.__call__(*arguments, **namedArguments)

def logwrap(function):
    return LogWrappedFunction(function).logAndCall

@logwrap
def doSomething(spam, eggs, foo, bar):
    print "Doing something totally awesome with %s and %s." % (spam, eggs)


doSomething("beans","rice", foo="wiggity", bar="wack")

运行它,它将产生以下输出:

C:\scripts>python decoratorExample.py
Calling doSomething with arguments ('beans', 'rice') and named arguments {'foo':
 'wiggity', 'bar': 'wack'}
Doing something totally awesome with beans and rice.

其他回答

现在dir()和vars()呢?

似乎做什么是被要求超级简单…

必须从函数范围内调用。

但要注意,它将返回所有局部变量,所以如果需要,请确保在函数的最开始执行。

还要注意,正如评论中指出的那样,这不允许从作用域之外执行此操作。所以不完全是OP的情况,但仍然符合题目。这就是我的回答。

在decorator方法中,你可以这样列出原始方法的参数:

import inspect, itertools 

def my_decorator():   
        def decorator(f):
            def wrapper(*args, **kwargs):
                # if you want arguments names as a list:
                args_name = inspect.getargspec(f)[0]
                print(args_name)

                # if you want names and values as a dictionary:
                args_dict = dict(itertools.izip(args_name, args))
                print(args_dict)

                # if you want values as a list:
                args_values = args_dict.values()
                print(args_values)

如果**狼对你来说很重要,那就有点复杂了:

def wrapper(*args, **kwargs):
    args_name = list(OrderedDict.fromkeys(inspect.getargspec(f)[0] + kwargs.keys()))
    args_dict = OrderedDict(list(itertools.izip(args_name, args)) + list(kwargs.iteritems()))
    args_values = args_dict.values()

例子:

@my_decorator()
def my_function(x, y, z=3):
    pass


my_function(1, y=2, z=3, w=0)
# prints:
# ['x', 'y', 'z', 'w']
# {'y': 2, 'x': 1, 'z': 3, 'w': 0}
# [1, 2, 3, 0]

在CPython中,参数的数量是

a_method.func_code.co_argcount

他们的名字在开头

a_method.func_code.co_varnames

这些是CPython的实现细节,所以这可能不适用于Python的其他实现,比如IronPython和Jython。

承认“传递”参数的一种可移植方法是使用func(*args, **kwargs)签名来定义函数。这在matplotlib中被大量使用,其中外层API层将大量关键字参数传递给底层API。

是否可以使用inspect API从下面的代码中的lambda func fun读取常量参数值-1 ?

def my_func(v, axis):
  pass

fun = lambda v: my_func(v, axis=-1)

在python 3中,下面是将*args和**kwargs放入dict(对于python < 3.6使用OrderedDict来维护dict顺序):

from functools import wraps

def display_param(func):
    @wraps(func)
    def wrapper(*args, **kwargs):

        param = inspect.signature(func).parameters
        all_param = {
            k: args[n] if n < len(args) else v.default
            for n, (k, v) in enumerate(param.items()) if k != 'kwargs'
        }
        all_param .update(kwargs)
        print(all_param)

        return func(**all_param)
    return wrapper