문제

파이썬 기능이 주어지면 :

def aMethod(arg1, arg2):
    pass

인수의 번호와 이름을 추출하려면 어떻게해야합니까? 즉, func에 대한 참조가 있다는 것을 감안할 때, 나는 func를 원한다.

이에 대한 사용 시나리오는 데코레이터가 있다는 것입니다. 메소드 인수를 실제 함수에 대해 키로 표시하는 것과 동일한 순서로 사용하고 싶습니다. 즉, Amethod ( "a", "b")를 호출 할 때 "A, B"를 인쇄 한 데코레이터는 어떻게 보입니까?

도움이 되었습니까?

해결책

살펴보십시오 검사 모듈 - 이것은 다양한 코드 객체 속성을 검사합니다.

>>> inspect.getfullargspec(aMethod)
(['arg1', 'arg2'], None, None, None)

다른 결과는 *args 및 ** kwargs 변수의 이름과 기본값이 제공됩니다. 즉.

>>> def foo(a,b,c=4, *arglist, **keywords): pass
>>> inspect.getfullargspec(foo)
(['a', 'b', 'c'], 'arglist', 'keywords', (4,))

일부 콜라블은 특정 Python 구현에서는 내성적이지 않을 수 있습니다. 예를 들어, CPYTHON에서 C에 정의 된 일부 내장 기능은 인수에 대한 메타 데이터를 제공하지 않습니다. 결과적으로, 당신은 얻을 것입니다 ValueError 당신이 사용하는 경우 inspect.getfullargspec() 내장 기능으로.

Python 3.3 이후로도 사용할 수 있습니다 검사 .signature () 호출 가능한 객체의 통화 서명을 알기 위해 :

>>> inspect.signature(foo)
<Signature (a, b, c=4, *arglist, **keywords)>

다른 팁

Cpython에서는 논쟁의 수가 있습니다

aMethod.func_code.co_argcount

그리고 그들의 이름은 시작에 있습니다

aMethod.func_code.co_varnames

이것들은 cpython의 구현 세부 사항이므로 Ironpython 및 Jython과 같은 다른 Python 구현에서는 작동하지 않을 것입니다.

"통과"인수를 인정하는 휴대용 방법 중 하나는 서명으로 기능을 정의하는 것입니다. func(*args, **kwargs). 이것은 외부 API 층이 많은 키워드 인수를 하위 레벨 API에 전달하는 예를 들어 Matplotlib에서 많이 사용됩니다.

데코레이터 방법에서는 원래 방법의 인수를 이런 방식으로 나열 할 수 있습니다.

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)

만약 **kwargs 당신에게 중요하다면 조금 복잡 할 것입니다.

        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]

다음은 데코레이터를 사용하여 원하는대로 작동 할 것이라고 생각합니다.

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.

나는 당신이 찾고있는 것이 현지인 방법이라고 생각합니다.


In [6]: def test(a, b):print locals()
   ...: 

In [7]: test(1,2)              
{'a': 1, 'b': 2}

Python 3 버전은 다음과 같습니다.

def _get_args_dict(fn, args, kwargs):
    args_names = fn.__code__.co_varnames[:fn.__code__.co_argcount]
    return {**dict(zip(args_names, args)), **kwargs}

이 방법은 Args와 Kwargs를 모두 포함하는 사전을 반환합니다.

파이썬 3.5+ :

감가 상각시기 : inspect.getArgspec ()가 더 이상 사용되지 않으 셨습니다.

그래서 이전 :

func_args = inspect.getargspec(function).args

지금:

func_args = list(inspect.signature(function).parameters.keys())

테스트하려면 :

'arg' in list(inspect.signature(function).parameters.keys())

인수 'arg'를 취하는 함수 '함수'가 있다는 점을 감안할 때, 이것은 사실로 평가됩니다. 그렇지 않으면 거짓으로 평가됩니다.

파이썬 콘솔의 예 :

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32
>>> import inspect
>>> 'iterable' in list(inspect.signature(sum).parameters.keys())
True

Python 3에서.+ Signature 인수 이름 사이에 값에 대한 매핑을 얻는 쉬운 방법 인 객체는 서명의 사용입니다. bind() 방법!

예를 들어, 다음은 다음과 같은지도를 인쇄하기위한 데코레이터입니다.

import inspect

def decorator(f):
    def wrapper(*args, **kwargs):
        bound_args = inspect.signature(f).bind(*args, **kwargs)
        bound_args.apply_defaults()
        print(dict(bound_args.arguments))

        return f(*args, **kwargs)

    return wrapper

@decorator
def foo(x, y, param_with_default="bars", **kwargs):
    pass

foo(1, 2, extra="baz")
# This will print: {'kwargs': {'extra': 'baz'}, 'param_with_default': 'bars', 'y': 2, 'x': 1}

인수 이름 목록을 반환하고 부분 및 정기적 인 기능을 처리합니다.

def get_func_args(f):
    if hasattr(f, 'args'):
        return f.args
    else:
        return list(inspect.signature(f).parameters)

업데이트 브라이언의 대답:

Python 3의 함수에 키워드 전용 인수가 있으면 사용해야합니다. inspect.getfullargspec:

def yay(a, b=10, *, c=20, d=30):
    pass
inspect.getfullargspec(yay)

이것을 생성합니다 :

FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(10,), kwonlyargs=['c', 'd'], kwonlydefaults={'c': 20, 'd': 30}, annotations={})

Python 3에서는 아래가 만들어야합니다 *args 그리고 **kwargs a dict (사용 OrderedDict Python <3.6 유지 관리 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

조금 업데이트하려면 브라이언의 대답, 이제 좋은 백포트가 있습니다 inspect.signature 오래된 파이썬 버전에서 사용할 수 있습니다. funcsigs. 그래서 내 개인적인 취향은 갈 것입니다

try:  # python 3.3+
    from inspect import signature
except ImportError:
    from funcsigs import signature

def aMethod(arg1, arg2):
    pass

sig = signature(aMethod)
print(sig)

재미를 위해, 당신은 함께 노는 데 관심이 있다면 Signature 무작위 서명으로 객체 및 기능을 동적으로 만들 수 있습니다. makefun 프로젝트.

는 어때 dir() 그리고 vars() 지금?

슈퍼에게 단순히 묻는 것을 정확하게하는 것 같습니다…

함수 범위 내에서 호출해야합니다.

그러나 그것이 돌아올 것이라고 조심하십시오 모두 로컬 변수 따라서 필요한 경우 기능의 시작 부분에 있어야합니다.

또한 주석에서 지적한 바와 같이, 이것은 범위 밖에서이를 수행 할 수 없습니다. 따라서 정확히 OP의 시나리오는 아니지만 여전히 질문 제목과 일치합니다. 따라서 내 대답.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top