Dalam Python, tanpa menggunakan traceback
modul, apakah ada cara untuk menentukan nama fungsi dari dalam fungsi itu?
Katakanlah saya punya modul foo dengan bilah fungsi. Saat menjalankan foo.bar()
, apakah ada cara bagi bar untuk mengetahui nama bar? Atau lebih baik lagi, foo.bar
nama?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
python
function
introspection
traceback
rampok
sumber
sumber
traceback
. Bahkan saat-saat jawaban dan komentar sepertinya tidak mendukungnya.Jawaban:
Python tidak memiliki fitur untuk mengakses fungsi atau namanya di dalam fungsi itu sendiri. Telah diusulkan tetapi ditolak. Jika Anda tidak ingin bermain sendiri dengan tumpukan, Anda harus menggunakan
"bar"
ataubar.__name__
bergantung pada konteks.Pemberitahuan penolakan yang diberikan adalah:
sumber
inspect.currentframe()
adalah salah satu cara seperti itu.print(inspect.currentframe().f_code.co_name)
sumber
[1][3]
untuk mendapatkan nama penelepon.print(inspect.currentframe().f_code.co_name)
atau untuk mendapatkan nama pemanggil:print(inspect.currentframe().f_back.f_code.co_name)
. Saya pikir itu harus lebih cepat karena Anda tidak mengambil daftar semua frame stack sepertiinspect.stack()
halnya.inspect.currentframe().f_back.f_code.co_name
tidak bekerja dengan metode yang didekorasi sedangkaninspect.stack()[0][3]
...Ada beberapa cara untuk mendapatkan hasil yang sama:
Perhatikan bahwa
inspect.stack
panggilan ribuan kali lebih lambat daripada alternatif:sumber
inspect.currentframe()
tampaknya pertukaran yang baik antara waktu eksekusi dan penggunaan anggota pribadi0.100 usec
atau0.199 usec
sebaliknya - ratusan kali lebih cepat dari opsi 1 dan 2, sebanding dengan opsi 4 (meskipun Antony Hatchkins menemukan opsi 3 tiga kali lebih cepat dari opsi 4).sys._getframe().f_code.co_name
lebihinspect.currentframe().f_code.co_name
karena saya sudah mengimporsys
modul. Apakah itu keputusan yang masuk akal? (mengingat kecepatan muncul sangat mirip)Anda bisa mendapatkan nama yang didefinisikan dengan menggunakan pendekatan yang ditunjukkan oleh @Andreas Jung , tapi itu mungkin bukan nama yang dipanggil dengan fungsi:
Apakah perbedaan itu penting bagi Anda atau tidak, saya tidak bisa mengatakannya.
sumber
.func_name
. Perlu diingat bahwa nama kelas dan nama fungsi dalam Python adalah satu hal dan variabel yang merujuk padanya adalah hal lain.Foo2()
mencetakFoo
. Sebagai contoh:Foo2 = function_dict['Foo']; Foo2()
. Dalam hal ini, Foo2 adalah pointer fungsi untuk mungkin parser baris perintah.Saya menginginkan hal yang sangat mirip karena saya ingin memasukkan nama fungsi dalam string log yang masuk ke sejumlah tempat dalam kode saya. Mungkin bukan cara terbaik untuk melakukan itu, tetapi inilah cara untuk mendapatkan nama fungsi saat ini.
sumber
f
untuk frame danco
kode. Saya tidak menggunakannya terlalu banyak sehingga lebih baik jika saya menyimpannya di beberapa cuplikan :-)Saya menyimpan utilitas praktis ini di dekat:
Pemakaian:
sumber
Saya kira
inspect
adalah cara terbaik untuk melakukan ini. Sebagai contoh:sumber
Saya menemukan pembungkus yang akan menulis nama fungsi
Ini akan dicetak
sumber
my_funky_name.__name__
. Anda bisa melewatkan func .__ name__ ke dalam fungsi sebagai parameter baru. func (* args, ** kwargs, my_name = func .__ name__). Untuk mendapatkan nama dekorator Anda dari dalam fungsi Anda, saya pikir itu perlu menggunakan inspeksi. Tetapi mendapatkan nama fungsi yang mengendalikan fungsi saya di dalam fungsi berlari saya ... yah itu terdengar seperti permulaan meme yang indah :)Ini sebenarnya berasal dari jawaban lain untuk pertanyaan itu.
Inilah pendapat saya:
Kemungkinan keuntungan dari versi ini daripada menggunakan inspect.stack () adalah bahwa itu harus ribuan kali lebih cepat [lihat posting dan waktu Alex Melihoff mengenai penggunaan sys._getframe () dibandingkan menggunakan inspect.stack ()].
sumber
print(inspect.stack()[0].function)
tampaknya berfungsi juga (Python 3.5).sumber
Berikut ini adalah pendekatan yang terbukti di masa depan.
Menggabungkan saran @ CamHart dan @ Yuval dengan jawaban yang diterima @ RoshOxymoron memiliki manfaat menghindari:
_hidden
dan metode yang berpotensi usangJadi saya pikir ini bagus untuk versi python masa depan (diuji pada 2.7.3 dan 3.3.2):
sumber
Uji:
Keluaran:
sumber
Saya tidak yakin mengapa orang membuatnya rumit:
sumber
Dalam IDE output kode
sumber
Anda dapat menggunakan dekorator:
sumber
__name__
atribut fungsi. Penggunaan membutuhkan mengetahui hal yang Anda coba dapatkan, yang tampaknya tidak terlalu berguna bagi saya dalam kasus sederhana di mana fungsi tidak didefinisikan dengan cepat.Saya melakukan pendekatan saya sendiri yang digunakan untuk memanggil super dengan aman di dalam beberapa skenario warisan (saya meletakkan semua kode)
penggunaan sampel:
mengujinya:
keluaran:
Di dalam setiap metode dihiasi @with_name Anda memiliki akses ke self .__ fname__ sebagai nama fungsi saat ini.
sumber
Saya baru-baru ini mencoba menggunakan jawaban di atas untuk mengakses dokumen dari suatu fungsi dari konteks fungsi itu tetapi karena pertanyaan di atas hanya mengembalikan string nama itu tidak berfungsi.
Untungnya saya menemukan solusi sederhana. Jika seperti saya, Anda ingin merujuk ke fungsi daripada hanya mendapatkan string yang mewakili nama yang dapat Anda terapkan eval () ke string nama fungsi.
sumber
Saya sarankan untuk tidak mengandalkan elemen stack. Jika seseorang menggunakan kode Anda dalam konteks yang berbeda (misalnya interpreter python) tumpukan Anda akan berubah dan menghancurkan indeks Anda ([0] [3]).
Saya menyarankan Anda sesuatu seperti itu:
sumber
Ini sangat mudah dilakukan dengan dekorator.
sumber