pytanie jest w pełni uzasadnione; gdyby tak nie było (ponieważ zawsze możesz odczytać źródło), nie byłoby żadnego uzasadnienia dla inspectstandardowego modułu biblioteki.
przepływ
Wiele języków zawiera co najmniej jedną nieuzasadnioną funkcję. inspectModuł posiada wiele innych funkcji, dlatego jest niesprawiedliwe powiedzieć, że cały moduł byłoby nieuzasadnione, jeśli jedna szczególna funkcja w nim było. Co więcej, łatwo jest zobaczyć, jak ta funkcja może być źle wykorzystana. (Zobacz stackoverflow.com/questions/741950 ). To powiedziawszy, jest to przydatna funkcja, szczególnie do pisania dekoratorów i innych funkcji, które działają na funkcję.
user1612868
Odpowiedzi:
131
Poprzednio zaakceptowana odpowiedź została wycofana z dnia Python 3.0. Zamiast używać inspect.getargspec, powinieneś teraz wybrać Signatureklasę, która go zastąpiła.
Tworzenie podpisu dla funkcji jest łatwe dzięki signaturefunkcji :
from inspect import signature
def someMethod(self, arg1, kwarg1=None):pass
sig = signature(someMethod)
Teraz możesz szybko wyświetlić jego parametry, strużywając go:
str(sig)# returns: '(self, arg1, kwarg1=None)'
lub możesz również uzyskać mapowanie nazw atrybutów na obiekty parametrów za pośrednictwem sig.parameters.
Dodatkowo, można zadzwonić lenna sig.parameterscelu również zobaczyć liczbę argumentów funkcja ta wymaga:
print(len(params))# 3
Każdy wpis w paramsmapowaniu jest w rzeczywistości Parameterobiektem, który ma dalsze atrybuty ułatwiające życie. Na przykład pobranie parametru i wyświetlenie jego wartości domyślnej można teraz łatwo wykonać za pomocą:
podobnie dla pozostałych obiektów zawartych w parameters.
Jeśli chodzi o 2.xużytkowników Pythona , chociaż inspect.getargspecnie jest przestarzały, język wkrótce będzie :-). SignatureKlasa nie jest dostępny w 2.xserii i nie będzie. Więc nadal musisz pracować inspect.getargspec.
Jeśli chodzi o przejście między Python 2 i 3, jeśli masz kod, który opiera się na interfejsie getargspecw Pythonie 2 i przełączania signaturesię 3to zbyt trudne, to trzeba cenną opcję korzystania inspect.getfullargspec. Oferuje podobny interfejs do getargspec(pojedynczy wywoływalny argument) w celu pobrania argumentów funkcji, jednocześnie obsługując kilka dodatkowych przypadków, które getargspecnie:
Nie ma za co @ GeorgSchölly. Zaskoczyło mnie popularne pytanie, takie jak to, które oferowało rozwiązania, które albo były przestarzałe, albo podstępne (zerkając w co_argcountatrybut).
Dimitris Fasarakis Hilliard
1
getfullargspecnie jest zaimplementowany w Pythonie 2.x, musisz użyćgetargspec
Peter Gibson
getargspecnie działa na funkcjach wbudowanych: getargspec(open)daje TypeError: <built-in function open> is not a Python functionZobacz tę odpowiedź dla niektórych pomysłów ...
starfry
W twoim ostatnim przykładzie, kiedy to robisz print(args), nie defaults=(None,)dostajesz defaults=None.
Seanny123,
si istnieje sposób na uzyskanie oryginalnej liczby parametrów funkcji, która została udekorowana po dekoracji ..?
Ogólnie to, czego chcesz, ale to nie działa w przypadku funkcji wbudowanych. Jedynym sposobem, aby dowiedzieć się, jak uzyskać te informacje dla wbudowanych, jest przeanalizowanie ich notki dokumentacyjnej , co jest błędne, ale wykonalne.
@elyase, po prostu zrób: dir(someMethod)-> 'func_code'; Idź dalej: dir(someMethod.func_code)-> 'co_argcount'; Możesz użyć wbudowanego, dir()aby określić dostępne metody obiektu.
Aby obsługiwać Python 3:six.get_function_code(someMethod).co_argcount
noisecapella
8
@noisecapella nie ma potrzeby stosowania zewnętrznego modułu, kiedy możesz po prostu to zrobićsome_method.__code__.co_argcount
vallentin
1
Ogólnie rzecz biorąc, nie powinieneś zaglądać do wnętrza obiektu funkcji, aby spojrzeć na te rzeczy. co_argcountjest używany wewnętrznie podczas oceny obiektu kodu. Próbuję powiedzieć, że naprawdę nie ma gwarancji, że te atrybuty nie zmienią się z jednej wersji na drugą.
Uzyskaj nazwy i domyślne wartości argumentów funkcji. Zwracana jest krotka czterech rzeczy: (args, varargs, varkw, defaults). args to lista nazw argumentów (może zawierać listy zagnieżdżone). varargs i varkw to nazwy argumentów * i ** lub None. defaults jest krotką domyślnych wartości argumentów lub None, jeśli nie ma domyślnych argumentów; jeśli ta krotka ma n elementów, odpowiadają one ostatnim n elementom wymienionym w args.
Zmienione w wersji 2.6: zwraca nazwaną krotkę ArgSpec (args, varargs, words, defaults).
Dodając do powyższego, zauważyłem również, że w większości przypadków funkcja help () naprawdę pomaga
Na przykład podaje wszystkie szczegóły dotyczące argumentów, które przyjmuje.
help(<method>)
podaje poniżej
method(self,**kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.Args:
date: string,Represents the date in yyyy-mm-dd format for which the data is to be fetched.(required)
pageToken: string,Token to specify next page.
parameters: string,Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.Returns:An object of the form:{# JSON template for a collection of usage reports."nextPageToken":"A String",# Token for retrieving the next page"kind":"admin#reports#usageReports",# Th
Byłoby dobrze, gdyby ludzie zostawili komentarz na temat tego, co jest nie tak z postem, niż kliknięcie przycisku minus.
Venu Murthy
2
helpfunkcja pokazuje tylko to, co mówi napis. Czy nawet przetestowałeś, czy działa z definicją funkcji w pytaniu?
0xc0de
@ 0xc0de - Czy to przetestowałeś? Ponieważ to faktycznie działa. help()wypluwa więcej niż tylko ciąg dokumentów - nawet w przypadku nieudokumentowanego kodu nadal wypisuje argument argspec i informuje, gdzie kod został zdefiniowany. Osoba, która opublikowała oryginalne pytanie, nie była pewna, czy potrzebuje odpowiedzi przyjaznej dla maszyny czy człowieka. Jeśli tylko ma być przyjazny człowiekowi, help()jest całkowicie wystarczający.
ArtOfWarfare
@ArtOfWarfare wcale nie, ponieważ teraz musiałbyś przeanalizować wszystko help(), co zwraca, i spróbować znaleźć argsi kwargs.
Vallentin
5
Dobra wiadomość dla osób, które chcą to zrobić w sposób przenośny między Pythonem 2 a Pythonem 3.6+: użyj inspect.getfullargspec() metody. Działa zarówno w Pythonie 2.x, jak i 3.6+
Jak zauważył Jim Fasarakis Hilliard i inni, kiedyś wyglądało to tak:
1. W Pythonie 2.x: użyj inspect.getargspec()
2. W Pythonie 3.x: użyj podpisu, as getargspec()i getfullargspec()zostały uznane za przestarzałe.
Jednak po uruchomieniu Pythona 3.6 (ze względu na popularne zapotrzebowanie?), Rzeczy zmieniły się w kierunku lepszych:
Zmieniono w wersji 3.6 : Ta metoda została wcześniej udokumentowana jako przestarzała na korzyść signature()w Pythonie 3.5, ale ta decyzja została cofnięta w celu przywrócenia wyraźnie obsługiwanego standardowego interfejsu dla kodu Python 2/3 z jednego źródła, który migrował ze starszego getargspec()interfejsu API.
Witamy w Stack Overflow! Nie odpowiadaj tylko za pomocą kodu źródłowego. Postaraj się przedstawić miły opis tego, jak działa Twoje rozwiązanie. Zobacz: Jak napisać dobrą odpowiedź? . Dzięki
sɐunıɔ ןɐ qɐp
2
Jak sugerują inne odpowiedzi, getargspecdziała dobrze, o ile pytana rzecz jest w rzeczywistości funkcją. To nie działa na wbudowanej funkcji, takich jak open, lenitd, i rzuci wyjątek w takich przypadkach:
TypeError:<built-in function open>isnot a Python function
Poniższa funkcja (zainspirowana tą odpowiedzią ) przedstawia obejście. Zwraca liczbę argumentów oczekiwaną przez f:
inspect
standardowego modułu biblioteki.inspect
Moduł posiada wiele innych funkcji, dlatego jest niesprawiedliwe powiedzieć, że cały moduł byłoby nieuzasadnione, jeśli jedna szczególna funkcja w nim było. Co więcej, łatwo jest zobaczyć, jak ta funkcja może być źle wykorzystana. (Zobacz stackoverflow.com/questions/741950 ). To powiedziawszy, jest to przydatna funkcja, szczególnie do pisania dekoratorów i innych funkcji, które działają na funkcję.Odpowiedzi:
Poprzednio zaakceptowana odpowiedź została wycofana z dnia
Python 3.0
. Zamiast używaćinspect.getargspec
, powinieneś teraz wybraćSignature
klasę, która go zastąpiła.Tworzenie podpisu dla funkcji jest łatwe dzięki
signature
funkcji :Teraz możesz szybko wyświetlić jego parametry,
str
używając go:lub możesz również uzyskać mapowanie nazw atrybutów na obiekty parametrów za pośrednictwem
sig.parameters
.Dodatkowo, można zadzwonić
len
nasig.parameters
celu również zobaczyć liczbę argumentów funkcja ta wymaga:Każdy wpis w
params
mapowaniu jest w rzeczywistościParameter
obiektem, który ma dalsze atrybuty ułatwiające życie. Na przykład pobranie parametru i wyświetlenie jego wartości domyślnej można teraz łatwo wykonać za pomocą:podobnie dla pozostałych obiektów zawartych w
parameters
.Jeśli chodzi o
2.x
użytkowników Pythona , chociażinspect.getargspec
nie jest przestarzały, język wkrótce będzie :-).Signature
Klasa nie jest dostępny w2.x
serii i nie będzie. Więc nadal musisz pracowaćinspect.getargspec
.Jeśli chodzi o przejście między Python 2 i 3, jeśli masz kod, który opiera się na interfejsie
getargspec
w Pythonie 2 i przełączaniasignature
się3
to zbyt trudne, to trzeba cenną opcję korzystaniainspect.getfullargspec
. Oferuje podobny interfejs dogetargspec
(pojedynczy wywoływalny argument) w celu pobrania argumentów funkcji, jednocześnie obsługując kilka dodatkowych przypadków, któregetargspec
nie:Podobnie jak w przypadku
getargspec
,getfullargspec
zwraca wartośćNamedTuple
zawierającą argumenty.źródło
co_argcount
atrybut).getfullargspec
nie jest zaimplementowany w Pythonie 2.x, musisz użyćgetargspec
getargspec
nie działa na funkcjach wbudowanych:getargspec(open)
dajeTypeError: <built-in function open> is not a Python function
Zobacz tę odpowiedź dla niektórych pomysłów ...print(args)
, niedefaults=(None,)
dostajeszdefaults=None
.zobacz moduł inspekcji
źródło
inspect.signature
- docs.python.org/3/library/inspect.html#inspect.signaturelub, jeśli nazwa bieżącej funkcji jest nieokreślona:
źródło
dir(someMethod)
->'func_code'
; Idź dalej:dir(someMethod.func_code)
->'co_argcount'
; Możesz użyć wbudowanego,dir()
aby określić dostępne metody obiektu.six.get_function_code(someMethod).co_argcount
some_method.__code__.co_argcount
co_argcount
jest używany wewnętrznie podczas oceny obiektu kodu. Próbuję powiedzieć, że naprawdę nie ma gwarancji, że te atrybuty nie zmienią się z jednej wersji na drugą.inspect.getargspec ()
Zobacz can-you-list-the-keyword-arguments-a-python-function-takes .
źródło
Dodając do powyższego, zauważyłem również, że w większości przypadków funkcja help () naprawdę pomaga
Na przykład podaje wszystkie szczegóły dotyczące argumentów, które przyjmuje.
podaje poniżej
źródło
help
funkcja pokazuje tylko to, co mówi napis. Czy nawet przetestowałeś, czy działa z definicją funkcji w pytaniu?help()
wypluwa więcej niż tylko ciąg dokumentów - nawet w przypadku nieudokumentowanego kodu nadal wypisuje argument argspec i informuje, gdzie kod został zdefiniowany. Osoba, która opublikowała oryginalne pytanie, nie była pewna, czy potrzebuje odpowiedzi przyjaznej dla maszyny czy człowieka. Jeśli tylko ma być przyjazny człowiekowi,help()
jest całkowicie wystarczający.help()
, co zwraca, i spróbować znaleźćargs
ikwargs
.Dobra wiadomość dla osób, które chcą to zrobić w sposób przenośny między Pythonem 2 a Pythonem 3.6+: użyj
inspect.getfullargspec()
metody. Działa zarówno w Pythonie 2.x, jak i 3.6+Jak zauważył Jim Fasarakis Hilliard i inni, kiedyś wyglądało to tak:
1. W Pythonie 2.x: użyj
inspect.getargspec()
2. W Pythonie 3.x: użyj podpisu, as
getargspec()
igetfullargspec()
zostały uznane za przestarzałe.Jednak po uruchomieniu Pythona 3.6 (ze względu na popularne zapotrzebowanie?), Rzeczy zmieniły się w kierunku lepszych:
Ze strony dokumentacji Python 3 :
źródło
inspect.getargspec () do Twoich potrzeb
źródło
Jak sugerują inne odpowiedzi,
getargspec
działa dobrze, o ile pytana rzecz jest w rzeczywistości funkcją. To nie działa na wbudowanej funkcji, takich jakopen
,len
itd, i rzuci wyjątek w takich przypadkach:Poniższa funkcja (zainspirowana tą odpowiedzią ) przedstawia obejście. Zwraca liczbę argumentów oczekiwaną przez
f
:Chodzi o to, aby wyodrębnić specyfikację funkcji z
__doc__
ciągu. Oczywiście zależy to od formatu wspomnianego ciągu, więc nie jest wytrzymałe!źródło
func.__code__.co_argcount
daje liczbę ewentualnych argumentów PRZED*args
func.__kwdefaults__
daje dykt argumentów słów kluczowych PO*args
func.__code__.co_kwonlyargcount
jest równelen(func.__kwdefaults__)
func.__defaults__
podaje wartości opcjonalnych argumentów, które pojawiają się wcześniej*args
Oto prosta ilustracja:
źródło
W:
Na zewnątrz:
Uwaga: Gdyby xyz nie należało do klasy X i nie zawierało „self”, a tylko „a, b, c”, to wypisałoby 3.
W przypadku Pythona poniżej 3.5 możesz zamienić
inspect.getfullargspec
goinspect.getargspec
na w powyższym kodzie.źródło