Załóżmy, że mam funkcję Python, jak zdefiniowano poniżej:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Mogę uzyskać nazwę funkcji za pomocą foo.func_name
. Jak mogę programowo uzyskać kod źródłowy, jak napisałem powyżej?
foo.__name__
Odpowiedzi:
Jeśli funkcja pochodzi z pliku źródłowego dostępnego w systemie plików,
inspect.getsource(foo)
może być pomocna:Jeśli
foo
jest zdefiniowany jako:Następnie:
Zwroty:
Uważam jednak, że jeśli funkcja jest skompilowana z ciągu, strumienia lub zaimportowana ze skompilowanego pliku, nie można pobrać jej kodu źródłowego.
źródło
len
. Gdzie mogę znaleźć kod źródłowylen
funkcji?inspect.getsourcelines(foo)
Sprawdzić moduł ma metody pobierania kodu źródłowego z obiektów Pythona. Pozornie działa to tylko wtedy, gdy źródło znajduje się w pliku. Gdybyś to miał, myślę, że nie musiałbyś pobierać źródła z obiektu.
źródło
python 3.5.3
tłumaczu.import inspect
+inspect.getsource(foo)
działało dobrze.dis
jest twoim przyjacielem, jeśli kod źródłowy nie jest dostępny:źródło
Jeśli używasz IPython, musisz wpisać „foo ??”
źródło
dir(MyClass)
, potemMyClass.__init__??
i tak dalej.Chociaż ogólnie zgadzam się, że
inspect
to dobra odpowiedź, nie zgadzam się z tym, że nie można uzyskać kodu źródłowego obiektów zdefiniowanych w tłumaczu. Jeśli używaszdill.source.getsource
zdill
, możesz uzyskać źródło funkcji i lambd, nawet jeśli są one zdefiniowane interaktywnie. Może również uzyskać kod z metod klasy i funkcji powiązanych lub niezwiązanych zdefiniowanych w curry ... jednak kompilacja tego kodu może nie być możliwa bez kodu obiektu otaczającego.źródło
dill.source.getsource
sprawdza historię interpretera pod kątem funkcji, klas, lambd itp. - nie sprawdza zawartości ciągów przekazywanych do exec.dill
odpowiedzi na to pytanie: stackoverflow.com/questions/13827543/…dill.source
Posiada funkcje jakgetname
iimportable
igetsource
które koncentrują się na uzyskaniu kodu źródłowego (lub importable że plony obiektu) dla danego obiektu. Dla prostych rzeczy, takich jak an,int
nie ma źródła, więc nie działa zgodnie z oczekiwaniami (tzn. Dla „a = 10” zwraca „10”).>>> a = 10; print( [key for key, val in globals().items() if val is a][0] )
dill
, ale moja odpowiedź pozostawia trochę do życzenia (IE, jeśli masz wiele nazw dla tej samej wartości, nie może ustalić, która została użyta. Jeśli przekazać wyrażenie, nie można powiedzieć, co to było wyrażenie. Cholera, jeśli podasz wyrażenie, które jest takie samo jak imię, nada mu to nazwę.) Możedill
rozwiązać dowolne z tych niedociągnięć mojej odpowiedzi tutaj: stackoverflow.com/a/28634996/901641Aby rozwinąć odpowiedź Runeha:
EDYCJA: Jak wskazano przez @ 0sh, ten przykład działa przy użyciu,
ipython
ale nie zwykłypython
. Jednak w przypadku importowania kodu z plików źródłowych powinno być dobrze w obu przypadkach.źródło
getsource(foo)
.Możesz użyć
inspect
modułu, aby uzyskać pełny kod źródłowy. Musisz użyćgetsource()
do tego metody zinspect
modułu. Na przykład:Możesz sprawdzić więcej opcji pod poniższym linkiem. pobierz swój kod python
źródło
Ponieważ ten post jest oznaczony jako duplikat tego drugiego postu , odpowiadam tutaj w sprawie „lambda”, chociaż OP nie dotyczy lambdas.
Tak więc, dla funkcji lambda, które nie są zdefiniowane we własnych liniach: oprócz odpowiedzi marko.ristin , możesz chcieć użyć mini-lambda lub użyć SymPy, jak sugerowano w tej odpowiedzi .
mini-lambda
jest lżejszy i obsługuje wszelkie operacje, ale działa tylko dla jednej zmiennejSymPy
jest cięższy, ale o wiele bardziej wyposażony w operacje matematyczne / rachunku różniczkowego. W szczególności może uprościć twoje wyrażenia. Obsługuje również kilka zmiennych w tym samym wyrażeniu.Oto jak możesz to zrobić za pomocą
mini-lambda
:Prawidłowo daje
Szczegółowe informacje można znaleźć w
mini-lambda
dokumentacji . Nawiasem mówiąc, jestem autorem;)źródło
Pamiętaj, że zaakceptowane odpowiedzi działają tylko wtedy, gdy lambda jest podana w osobnym wierszu. Jeśli przekażesz go jako argument funkcji i chcesz pobrać kod lambda jako obiekt, problem stanie się nieco trudny, ponieważ
inspect
da ci całą linię.Rozważmy na przykład plik
test.py
:Wykonanie go daje (uwaga na wcięcie!):
Aby pobrać kod źródłowy lambda, moim zdaniem najlepiej jest ponownie przeanalizować cały plik źródłowy (przy użyciu
f.__code__.co_filename
) i dopasować węzeł AST lambda według numeru linii i jego kontekstu.Musieliśmy zrobić dokładnie, że w naszym design-by-umowy biblioteki icontract ponieważ mieliśmy do analizowania funkcje lambda Mijamy się jako argumenty dekoratorów. Jest tu za dużo kodu do wklejenia, więc spójrz na implementację tej funkcji .
źródło
Jeśli ściśle definiujesz funkcję samodzielnie i jest to stosunkowo krótka definicja, rozwiązaniem bez zależności byłoby zdefiniowanie funkcji w ciągu i przypisanie funkcji eval () wyrażeniu do funkcji.
Na przykład
następnie opcjonalnie, aby dołączyć oryginalny kod do funkcji:
źródło
podsumowując:
źródło
Uważam , że nazwy zmiennych nie są przechowywane w plikach pyc / pyd / pyo, więc nie możesz pobrać dokładnych wierszy kodu, jeśli nie masz plików źródłowych.
źródło