Misalkan saya memiliki fungsi Python seperti yang didefinisikan di bawah ini:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Saya bisa mendapatkan nama fungsi menggunakan foo.func_name
. Bagaimana saya bisa mendapatkan kode sumber secara terprogram, seperti yang saya ketikkan di atas?
foo.__name__
Jawaban:
Jika fungsinya dari file sumber yang tersedia di sistem file, maka
inspect.getsource(foo)
mungkin bisa membantu:Jika
foo
didefinisikan sebagai:Kemudian:
Pengembalian:
Tetapi saya percaya bahwa jika fungsi dikompilasi dari string, stream atau diimpor dari file yang dikompilasi, maka Anda tidak dapat mengambil kode sumbernya.
sumber
len
. Di mana saya dapat menemukan kode sumber untuklen
fungsi ini?inspect.getsourcelines(foo)
The memeriksa modul memiliki metode untuk mengambil kode sumber dari objek python. Tampaknya itu hanya berfungsi jika sumbernya berada dalam file sekalipun. Jika Anda punya itu saya kira Anda tidak perlu mendapatkan sumber dari objek.
sumber
python 3.5.3
juru bahasa.import inspect
+inspect.getsource(foo)
bekerja dengan baik.dis
adalah teman Anda jika kode sumber tidak tersedia:sumber
Jika Anda menggunakan IPython, maka Anda perlu mengetik "foo ??"
sumber
dir(MyClass)
laluMyClass.__init__??
dan seterusnya.Meskipun saya umumnya setuju bahwa itu
inspect
adalah jawaban yang baik, saya tidak setuju bahwa Anda tidak bisa mendapatkan kode sumber objek yang didefinisikan dalam interpreter. Jika Anda menggunakandill.source.getsource
daridill
, Anda bisa mendapatkan sumber fungsi dan lambda, bahkan jika mereka didefinisikan secara interaktif. Ia juga bisa mendapatkan kode dari metode dan fungsi kelas yang diikat atau tidak terikat yang didefinisikan dalam kari ... namun, Anda mungkin tidak dapat mengkompilasi kode itu tanpa kode objek yang dilampirkan.sumber
dill.source.getsource
memeriksa sejarah penerjemah untuk fungsi, kelas, lambdas, dll - itu tidak memeriksa konten string yang diteruskan ke exec.dill
untuk menjawab pertanyaan ini: stackoverflow.com/questions/13827543/…dill.source
memiliki fungsi sepertigetname
danimportable
dangetsource
yang berfokus pada mendapatkan kode sumber (atau yang dapat diimpor yang menghasilkan objek) untuk objek yang diberikan. Untuk hal-hal sederhana sepertiint
tidak ada sumber, sehingga tidak berfungsi seperti yang diharapkan (yaitu untuk 'a = 10' ia mengembalikan '10').>>> a = 10; print( [key for key, val in globals().items() if val is a][0] )
dill
, tetapi jawaban saya meninggalkan sedikit yang diinginkan (yaitu, jika Anda memiliki beberapa nama untuk nilai yang sama, itu tidak dapat mencari tahu yang digunakan. Jika Anda lewat sebuah ekspresi, itu tidak bisa mengatakan apa ekspresi itu. Heck, jika Anda memasukkan ekspresi yang mengevaluasi sama dengan nama, itu akan memberikan nama itu sebagai gantinya.) Dapatdill
memecahkan semua kekurangan jawaban saya di sini: stackoverflow.com/a/28634996/901641Untuk memperluas jawaban runeh:
EDIT: Seperti yang ditunjukkan oleh @ 0sh contoh ini berfungsi menggunakan
ipython
tetapi tidak sederhanapython
. Namun, keduanya harus baik ketika mengimpor kode dari file sumber.sumber
getsource(foo)
.Anda dapat menggunakan
inspect
modul untuk mendapatkan kode sumber lengkap untuk itu. Anda harus menggunakangetsource()
metode untuk itu dariinspect
modul. Sebagai contoh:Anda dapat memeriksanya lebih banyak opsi pada tautan di bawah ini. ambil kode python Anda
sumber
Karena pos ini ditandai sebagai duplikat dari pos lain ini , saya jawab di sini untuk kasus "lambda", meskipun OP bukan tentang lambda.
Jadi, untuk fungsi lambda yang tidak didefinisikan dalam baris mereka sendiri: selain jawaban marko.ristin , Anda mungkin ingin menggunakan mini-lambda atau menggunakan SymPy seperti yang disarankan dalam jawaban ini .
mini-lambda
lebih ringan dan mendukung segala jenis operasi, tetapi hanya berfungsi untuk satu variabelSymPy
lebih berat tetapi jauh lebih dilengkapi dengan operasi matematika / kalkulus. Secara khusus itu dapat menyederhanakan ekspresi Anda. Ini juga mendukung beberapa variabel dalam ekspresi yang sama.Berikut ini cara melakukannya
mini-lambda
:Ini menghasilkan dengan benar
Lihat
mini-lambda
dokumentasi untuk detailnya. Aku pengarangnya;)sumber
Harap diingat bahwa jawaban yang diterima hanya berfungsi jika lambda diberikan pada baris terpisah. Jika Anda meneruskannya sebagai argumen ke fungsi dan ingin mengambil kode lambda sebagai objek, masalahnya menjadi sedikit rumit karena
inspect
akan memberi Anda seluruh baris.Misalnya, pertimbangkan sebuah file
test.py
:Melaksanakannya memberi Anda (ingatlah indensi!):
Untuk mengambil kode sumber lambda, taruhan terbaik Anda, menurut saya, adalah mengurai kembali seluruh file sumber (dengan menggunakan
f.__code__.co_filename
) dan mencocokkan node lambda AST dengan nomor baris dan konteksnya.Kami harus melakukan tepat bahwa di perpustakaan kami desain-by-kontrak icontract karena kami harus mengurai fungsi lambda kita lulus sebagai argumen untuk dekorator. Terlalu banyak kode untuk disisipkan di sini, jadi lihat implementasi dari fungsi ini .
sumber
Jika Anda benar-benar mendefinisikan fungsi sendiri dan itu adalah definisi yang relatif singkat, solusi tanpa dependensi adalah mendefinisikan fungsi dalam sebuah string dan menetapkan eval () ekspresi untuk fungsi Anda.
Misalnya
kemudian secara opsional untuk melampirkan kode asli ke fungsi:
sumber
untuk meringkas :
sumber
Saya percaya bahwa nama variabel tidak disimpan dalam file pyc / pyd / pyo, jadi Anda tidak dapat mengambil baris kode yang tepat jika Anda tidak memiliki file sumber.
sumber