Contoh sederhana. Dua metode, satu dipanggil dari yang lain:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
Dengan Python kita bisa mendeklarasikan def
di dalam yang lain def
. Jadi, jika method_b
diperlukan dan dipanggil hanya dari method_a
, haruskah saya menyatakan method_b
di dalam method_a
? seperti ini :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Atau haruskah saya menghindari melakukan ini?
python
coding-style
nukl
sumber
sumber
method_b
? (@inspector: Anda benar-benar perlu, tetapi ini sangat berguna ketika Anda masuk ke sedikit pemrograman fungsional, khususnya penutupan).Jawaban:
Apakah ini yang Anda cari? Ini disebut penutupan .
sumber
do_it()
mungkin akan sedikit lebih rumit daripada apa yang bisa ditangani oleh beberapa aritmatika dalam satureturn
pernyataan.Anda tidak benar-benar mendapatkan banyak dengan melakukan ini, bahkan melambat
method_a
karena akan mendefinisikan dan mengkompilasi ulang fungsi lain setiap kali dipanggil. Mengingat itu, mungkin akan lebih baik untuk hanya awalan nama fungsi dengan garis bawah untuk menunjukkan itu metode pribadi - yaitu_method_b
.Saya kira Anda mungkin ingin melakukan ini jika definisi fungsi bersarang bervariasi setiap kali karena beberapa alasan, tetapi itu mungkin menunjukkan kesalahan dalam desain Anda. Yang mengatakan, ada adalah alasan yang sah untuk melakukan hal ini untuk memungkinkan fungsi bersarang menggunakan argumen yang dilewatkan ke fungsi luar tapi tidak secara eksplisit diteruskan kepada mereka, yang kadang-kadang terjadi ketika menulis dekorator fungsi, misalnya. Itu yang ditunjukkan dalam jawaban yang diterima meskipun dekorator tidak didefinisikan atau digunakan.
Memperbarui:
Inilah bukti bahwa bersarangnya lebih lambat (menggunakan Python 3.6.1), meskipun diakui tidak banyak dalam kasus sepele ini:
Catatan saya menambahkan beberapa
self
argumen ke fungsi sampel Anda untuk membuatnya lebih seperti metode nyata (meskipunmethod_b2
secara teknis masih bukan metodeTest
kelas). Fungsi bersarang juga disebut dalam versi itu, tidak seperti milik Anda.sumber
method_b = self._method_b
dan kemudian meneleponmethod_b
untuk menghindari pencarian atribut berulang. (Kebetulan saya telah melakukan BANYAK pengaturan waktu belakangan ini. :)Fungsi di dalam fungsi biasanya digunakan untuk penutupan .
(Ada banyak perdebatan tentang apa yang sebenarnya membuat penutupan menjadi penutupan .)
Berikut ini contoh menggunakan built-in
sum()
. Ini mendefinisikanstart
sekali dan menggunakannya sejak saat itu:Digunakan:
Built-in python closure
functools.partial
adalah contoh penutupan.Dari python docs , kira-kira sama dengan:
(Kudos ke @ user225312 di bawah untuk jawabannya. Saya menemukan contoh ini lebih mudah untuk diketahui, dan mudah-mudahan akan membantu menjawab komentar @ mangga.)
sumber
Secara umum, tidak, jangan mendefinisikan fungsi di dalam fungsi.
Kecuali Anda memiliki alasan yang sangat bagus. Yang mana tidak.
Kenapa tidak?
lambda
ekspresi .Apa adalah alasan yang sangat baik untuk mendefinisikan fungsi dalam fungsi?
Ketika apa yang sebenarnya Anda inginkan adalah penutupan dingdang .
sumber
Sebenarnya tidak masalah untuk mendeklarasikan satu fungsi di dalam fungsi lainnya. Ini berguna khusus membuat dekorator.
Namun, sebagai aturan praktis, jika fungsinya kompleks (lebih dari 10 baris), mungkin lebih baik untuk mendeklarasikannya pada level modul.
sumber
Saya menemukan pertanyaan ini karena saya ingin mengajukan pertanyaan mengapa ada dampak kinerja jika seseorang menggunakan fungsi bersarang. Saya menjalankan tes untuk fungsi-fungsi berikut menggunakan Python 3.2.5 pada Notebook Windows dengan prosesor Intel Core i5-2530M Quad Core 2.5 GHz 2.5 GHz
Saya mengukur 20 kali berikut, juga untuk square1, square2, dan square5:
dan mendapat hasil sebagai berikut
square0
tidak memiliki fungsi bersarang,square1
memiliki satu fungsi bersarang,square2
memiliki dua fungsi bersarang dansquare5
memiliki lima fungsi bersarang. Fungsi bersarang hanya dideklarasikan tetapi tidak dipanggil.Jadi, jika Anda telah menetapkan 5 fungsi tersarang dalam fungsi yang tidak Anda panggil maka waktu eksekusi dari fungsi tersebut adalah dua kali dari fungsi tanpa fungsi bersarang. Saya pikir harus berhati-hati saat menggunakan fungsi bersarang.
File Python untuk seluruh tes yang menghasilkan output ini dapat ditemukan di ideone .
sumber
Itu hanya prinsip tentang API eksposur.
Menggunakan python, Ini ide yang bagus untuk menghindari paparan API di luar angkasa (modul atau kelas), fungsinya adalah tempat enkapsulasi yang baik.
Itu bisa jadi ide yang bagus. ketika Anda memastikan
Meskipun demikian, penyalahgunaan teknik ini dapat menyebabkan masalah dan menyiratkan cacat desain.
Hanya dari exp saya, Mungkin salah paham pertanyaan Anda.
sumber
Jadi pada akhirnya sebagian besar pertanyaan tentang seberapa pintar implementasi python adalah atau tidak, terutama dalam kasus fungsi dalam tidak menjadi penutup tetapi hanya dalam fungsi yang dibutuhkan penolong saja.
Dalam desain bersih yang dapat dimengerti hanya memiliki fungsi di mana mereka dibutuhkan dan tidak diekspos di tempat lain adalah desain yang baik apakah mereka tertanam dalam modul, kelas sebagai metode, atau di dalam fungsi atau metode lain. Ketika dilakukan dengan baik, mereka benar-benar meningkatkan kejelasan kode.
Dan ketika fungsi bagian dalam adalah penutup yang juga dapat membantu dengan kejelasan sedikit bahkan jika fungsi itu tidak dikembalikan dari fungsi yang mengandung untuk digunakan di tempat lain.
Jadi saya akan mengatakan secara umum menggunakannya tetapi waspada terhadap kemungkinan hit kinerja ketika Anda benar-benar khawatir tentang kinerja dan hanya menghapusnya jika Anda membuat profil aktual yang menunjukkan mereka sebaiknya dihapus.
Jangan lakukan optimasi prematur hanya dengan menggunakan "fungsi dalam BURUK" di seluruh kode python yang Anda tulis. Silahkan.
sumber
Tidak apa-apa melakukannya seperti itu, tetapi kecuali jika Anda perlu menggunakan penutupan atau mengembalikan fungsi saya mungkin akan dimasukkan ke tingkat modul. Saya membayangkan dalam contoh kode kedua yang Anda maksud:
jika tidak, some_data akan menjadi fungsinya.
Setelah itu di tingkat modul akan memungkinkan fungsi lain menggunakan method_b () dan jika Anda menggunakan sesuatu seperti Sphinx (dan autodoc) untuk dokumentasi, itu akan memungkinkan Anda untuk mendokumentasikan method_b juga.
Anda juga mungkin ingin mempertimbangkan hanya menempatkan fungsionalitas dalam dua metode di kelas jika Anda melakukan sesuatu yang dapat diwakili oleh suatu objek. Ini juga mengandung logika jika hanya itu yang Anda cari.
sumber
Lakukan sesuatu seperti:
jika Anda menjalankannya
some_function()
maka akan menjalankansome_other_function()
dan mengembalikan 42.EDIT: Saya awalnya menyatakan bahwa Anda tidak boleh mendefinisikan fungsi di dalam yang lain tapi itu menunjukkan bahwa praktis untuk melakukan hal ini kadang-kadang.
sumber
Anda dapat menggunakannya untuk menghindari mendefinisikan variabel global. Ini memberi Anda alternatif untuk desain lain. 3 desain menghadirkan solusi untuk masalah.
A) Menggunakan fungsi tanpa global
B) Menggunakan fungsi dengan global
C) Menggunakan fungsi di dalam fungsi lain
Solusi C) memungkinkan untuk menggunakan variabel dalam lingkup fungsi luar tanpa harus menyatakannya dalam fungsi dalam. Mungkin bermanfaat dalam beberapa situasi.
sumber
Function In function python
sumber