Biorąc pod uwagę funkcję Python:
def a_method(arg1, arg2):
pass
Jak mogę wyodrębnić liczbę i nazwy argumentów. To znaczy, biorąc pod uwagę, że mam odniesienie func
, chcę func.[something]
wrócić ("arg1", "arg2")
.
Scenariusz użycia jest taki, że mam dekorator i chcę użyć argumentów metody w tej samej kolejności, w jakiej pojawiają się dla rzeczywistej funkcji jako klucza. To znaczy, jak wyglądałby dekorator wydrukowany, "a,b"
kiedy dzwonię a_method("a", "b")
?
Odpowiedzi:
Spójrz na
inspect
moduł - przeprowadzi to kontrolę różnych właściwości obiektu kodu.Pozostałe wyniki to nazwa zmiennych * args i ** kwargs oraz podane wartości domyślne. to znaczy.
Zauważ, że niektóre wywołania mogą nie być introspektywne w niektórych implementacjach Pythona. Na przykład w CPython niektóre wbudowane funkcje zdefiniowane w C nie dostarczają metadanych dotyczących ich argumentów. W rezultacie otrzymasz,
ValueError
jeśli użyjeszinspect.getfullargspec()
wbudowanej funkcji.Od wersji Python 3.3 możesz używać
inspect.signature()
podpisu wywołania obiektu na żądanie:źródło
(4,)
odpowiadac
konkretnie parametrowi słowa kluczowego ?inspect.getargspec
jest przestarzały , ale zastępujeinspect.getfullargspec
.W CPython liczba argumentów wynosi
a ich imiona są na początku
Są to szczegóły implementacji CPython, więc prawdopodobnie nie działa to w innych implementacjach Pythona, takich jak IronPython i Jython.
Jednym przenośnym sposobem na dopuszczenie argumentów „pass-through” jest zdefiniowanie funkcji za pomocą podpisu
func(*args, **kwargs)
. Jest to często używane np. W matplotlib , gdzie zewnętrzna warstwa API przekazuje wiele argumentów słów kluczowych do API niższego poziomu.źródło
*args
, np .:def foo(x, *args, y, **kwargs): # foo.__code__.co_argcount == 1
W metodzie dekoratora możesz wyświetlić listę argumentów oryginalnej metody w następujący sposób:
Jeśli
**kwargs
są dla Ciebie ważne, będzie to trochę skomplikowane:Przykład:
źródło
Myślę, że szukasz metody lokalnej -
źródło
Wersja Python 3 to:
Metoda zwraca słownik zawierający zarówno argumenty, jak i kwargs.
źródło
[:fn.__code__.co_argcount]
jest to bardzo ważne, jeśli szukasz argumentów funkcji - w przeciwnym razie obejmuje to również nazwy utworzone w funkcji.Oto coś, co myślę, że będzie działać na to, czego chcesz, używając dekoratora.
Uruchom go, da następujące wyniki:
źródło
Python 3.5+:
Więc wcześniej:
Teraz:
Testować:
Biorąc pod uwagę, że mamy funkcję „function”, która przyjmuje argument „arg”, będzie to oceniane jako True, w przeciwnym razie jako False.
Przykład z konsoli Python:
źródło
W Pythonie 3. +, mając
Signature
pod ręką obiekt, łatwym sposobem uzyskania mapowania między nazwami argumentów a wartościami jest użycie podpisubind()
!Na przykład tutaj jest dekorator do drukowania takiej mapy:
źródło
Oto inny sposób uzyskania parametrów funkcji bez użycia żadnego modułu.
Wynik:
źródło
Zwraca listę nazw argumentów, dba o częściowe i regularne funkcje:
źródło
Aktualizacja odpowiedzi Briana :
Jeśli funkcja w Pythonie 3 zawiera argumenty zawierające tylko słowa kluczowe, musisz użyć
inspect.getfullargspec
:daje to:
źródło
W Pythonie 3 poniżej znajduje się polecenie make
*args
i**kwargs
intodict
(użyjOrderedDict
dla Pythona <3.6 do utrzymaniadict
zamówień):źródło
inspect.signature
jest bardzo wolny. Najszybszy sposób toźródło
Aby zaktualizować trochę odpowiedź Briana , nie ma teraz ładne backport z
inspect.signature
których można korzystać w starszych wersjach Pythona:funcsigs
. Tak więc poszłyby moje osobiste preferencjeDla zabawy, jeśli chcesz grać z
Signature
obiektami, a nawet dynamicznie tworzyć funkcje z losowymi podpisami, możesz rzucić okiem na mójmakefun
projekt.źródło
Co teraz
dir()
ivars()
teraz?Wydaje się, że robienie dokładnie tego, o co proszono, po prostu…
Należy wywołać z zakresu funkcji.
Ale bądź ostrożny, że zwróci wszystkie zmienne lokalne, więc w razie potrzeby zrób to na samym początku funkcji.
Należy również zauważyć, że, jak wskazano w komentarzach, nie pozwala to zrobić spoza zakresu. Więc nie do końca scenariusz OP, ale nadal pasuje do tytułu pytania. Stąd moja odpowiedź.
źródło