Saya tahu bahwa __call__
metode dalam suatu kelas dipicu ketika instance dari sebuah kelas dipanggil. Namun, saya tidak tahu kapan saya bisa menggunakan metode khusus ini, karena orang dapat dengan mudah membuat metode baru dan melakukan operasi yang sama dilakukan dalam __call__
metode dan alih-alih memanggil contoh, Anda dapat memanggil metode.
Saya akan sangat menghargai jika seseorang memberi saya penggunaan praktis metode khusus ini.
python
methods
call
magic-methods
mohi666
sumber
sumber
__call__
disembunyikan dalam tampilan biasa; itu bagaimana Anda instantiate kelas:x = Foo()
benar-benarx = type(Foo).__call__(Foo)
, di mana__call__
didefinisikan oleh metaclass dariFoo
.Jawaban:
Modul formulir Django menggunakan
__call__
metode dengan baik untuk mengimplementasikan API yang konsisten untuk validasi formulir. Anda dapat menulis validator Anda sendiri untuk formulir di Django sebagai fungsi.Django memiliki beberapa validator bawaan bawaan seperti validator email, validator url dll., Yang secara luas berada di bawah payung validator RegEx. Untuk mengimplementasikan ini dengan bersih, Django menggunakan kelas yang dapat dipanggil (alih-alih fungsi). Ini menerapkan logika Validasi Regex default di RegexValidator dan kemudian memperluas kelas-kelas ini untuk validasi lainnya.
Sekarang fungsi kustom Anda dan EmailValidator bawaan dapat dipanggil dengan sintaks yang sama.
Seperti yang Anda lihat, implementasi di Django ini mirip dengan apa yang orang lain jelaskan dalam jawaban mereka di bawah ini. Bisakah ini diimplementasikan dengan cara lain? Anda bisa, tetapi IMHO itu tidak akan mudah dibaca atau mudah diperluas untuk kerangka kerja besar seperti Django.
sumber
Contoh ini menggunakan memoisasi , yang pada dasarnya menyimpan nilai dalam sebuah tabel (kamus dalam kasus ini) sehingga Anda dapat mencarinya nanti alih-alih menghitung ulang.
Di sini kita menggunakan kelas sederhana dengan
__call__
metode untuk menghitung faktorial (melalui objek yang bisa dipanggil ) alih-alih fungsi faktorial yang berisi variabel statis (karena itu tidak mungkin dengan Python).Sekarang Anda memiliki
fact
objek yang dapat dipanggil, sama seperti fungsi lainnya. Sebagai contohDan itu juga stateful.
sumber
fact
objek yang dapat diindeks karena__call__
fungsi Anda pada dasarnya adalah indeks. Juga akan menggunakan daftar alih-alih dict, tapi itu hanya saya.__call__
, sederhana dan tidak lebih.Saya merasa berguna karena memungkinkan saya untuk membuat API yang mudah digunakan (Anda memiliki beberapa objek yang dapat dipanggil yang memerlukan beberapa argumen tertentu), dan mudah diterapkan karena Anda dapat menggunakan praktik Berorientasi Objek.
Berikut ini adalah kode yang saya tulis kemarin yang membuat versi
hashlib.foo
metode yang hash seluruh file daripada string:Implementasi ini memungkinkan saya untuk menggunakan fungsi dengan cara yang mirip dengan
hashlib.foo
fungsi:Tentu saja saya bisa menerapkannya dengan cara yang berbeda, tetapi dalam kasus ini sepertinya pendekatan yang sederhana.
sumber
__call__
memberi Anda alat yang memungkinkan Anda menggunakan teknik OO untuk memecahkan masalah.isinstance
atau sesuatu yang serupa.__call__
metode daripada penutupan adalah ketika Anda berurusan dengan modul multiprosesing, yang menggunakan pengawetan untuk meneruskan informasi antar proses. Anda tidak bisa membuat acar penutupan, tetapi Anda bisa acar contoh kelas.__call__
juga digunakan untuk mengimplementasikan kelas dekorator dalam python. Dalam hal ini instance dari kelas dipanggil ketika metode dengan dekorator dipanggil.sumber
Ya, ketika Anda tahu Anda berurusan dengan objek, sangat mungkin (dan dalam banyak kasus disarankan) untuk menggunakan pemanggilan metode eksplisit. Namun, kadang-kadang Anda berurusan dengan kode yang mengharapkan objek yang dapat dipanggil - biasanya berfungsi, tetapi berkat
__call__
Anda dapat membangun objek yang lebih kompleks, dengan data contoh dan lebih banyak metode untuk mendelegasikan tugas berulang, dll. Yang masih dapat dipanggil.Juga, kadang-kadang Anda menggunakan kedua objek untuk tugas-tugas kompleks (di mana masuk akal untuk menulis kelas khusus) dan objek untuk tugas-tugas sederhana (yang sudah ada dalam fungsi, atau lebih mudah ditulis sebagai fungsi). Untuk memiliki antarmuka umum, Anda harus menulis kelas kecil yang membungkus fungsi-fungsi tersebut dengan antarmuka yang diharapkan, atau Anda menjaga fungsi fungsi dan membuat objek yang lebih kompleks dapat dipanggil. Mari kita ambil utas sebagai contoh. The
Thread
benda dari modul libary standarthreading
ingin callable sebagaitarget
argumen (yaitu sebagai tindakan yang akan dilakukan di thread baru). Dengan objek yang dapat dipanggil, Anda tidak terbatas pada fungsi, Anda dapat melewati objek lain juga, seperti pekerja yang relatif kompleks yang mendapatkan tugas untuk dilakukan dari utas lain dan menjalankannya secara berurutan:Ini hanya contoh dari atas kepala saya, tetapi saya pikir itu sudah cukup kompleks untuk menjamin kelas. Melakukan ini hanya dengan fungsi itu sulit, setidaknya memerlukan mengembalikan dua fungsi dan itu perlahan semakin kompleks. Seseorang dapat mengubah nama
__call__
menjadi sesuatu yang lain dan melewati metode terikat, tetapi itu membuat kode membuat utas sedikit kurang jelas, dan tidak menambah nilai apa pun.sumber
__call__
digunakan untuk menggunakan instance kelas (bukan fungsi) sebagai aplikasi WSGI. Berikut adalah contoh dari "The Definitive Guide to Pylons": Menggunakan Instances of ClassesDekorator berbasis kelas digunakan
__call__
untuk referensi fungsi yang dibungkus. Misalnya:Ada deskripsi yang baik tentang berbagai opsi di sini di Artima.com
sumber
__call__
Metode dan penutupan IMHO memberi kita cara alami untuk membuat pola desain STRATEGI dengan Python. Kami mendefinisikan sekelompok algoritma, merangkum masing-masing, membuatnya dipertukarkan dan pada akhirnya kami dapat menjalankan serangkaian langkah-langkah umum dan, misalnya, menghitung hash untuk file.sumber
Saya hanya menemukan penggunaan
__call__()
dalam konser__getattr__()
yang menurut saya indah. Ini memungkinkan Anda untuk menyembunyikan beberapa level API JSON / HTTP / (yet_serialized) di dalam suatu objek.Bagian
__getattr__()
menangani iteratif mengembalikan instance yang dimodifikasi dari kelas yang sama, mengisi satu atribut lagi pada suatu waktu. Kemudian, setelah semua informasi habis,__call__()
ambil alih dengan argumen apa pun yang Anda sampaikan.Menggunakan model ini, misalnya Anda dapat membuat panggilan seperti
api.v2.volumes.ssd.update(size=20)
, yang berakhir dengan permintaan PUT kehttps://some.tld/api/v2/volumes/ssd/update
.Kode tertentu adalah driver penyimpanan blok untuk backend volume tertentu di OpenStack, Anda dapat memeriksanya di sini: https://github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py
SUNTING: Memperbarui tautan menuju revisi utama.
sumber
Tentukan
__metaclass__
dan timpa__call__
metode, dan minta metode meta class yang ditentukan__new__
mengembalikan instance kelas, biola Anda memiliki "fungsi" dengan metode.sumber
Kita dapat menggunakan
__call__
metode untuk menggunakan metode kelas lain sebagai metode statis.sumber
Salah satu contoh umum adalah
__call__
difunctools.partial
, di sini adalah versi yang disederhanakan (dengan Python> = 3.5):Pemakaian:
sumber
Operator panggilan fungsi.
The __call__ metode dapat digunakan untuk didefinisikan ulang / re-menginisialisasi objek yang sama. Ini juga memfasilitasi penggunaan instance / objek kelas sebagai fungsi dengan meneruskan argumen ke objek.
sumber
Aku menemukan tempat yang baik untuk menggunakan benda-benda callable, mereka yang menentukan
__call__()
, adalah ketika menggunakan kemampuan pemrograman fungsional dengan Python, sepertimap()
,filter()
,reduce()
.Waktu terbaik untuk menggunakan objek yang dapat dipanggil pada fungsi polos atau fungsi lambda adalah ketika logikanya kompleks dan perlu mempertahankan beberapa keadaan atau menggunakan info lain yang tidak diteruskan ke
__call__()
fungsi tersebut.Berikut adalah beberapa kode yang memfilter nama file berdasarkan ekstensi nama file mereka menggunakan objek dan callable
filter()
.Callable:
Pemakaian:
Keluaran:
sumber
Ini sudah terlambat tapi saya memberi contoh. Bayangkan Anda memiliki
Vector
kelas danPoint
kelas. Keduanya mengambilx, y
argumen posisi. Bayangkan Anda ingin membuat fungsi yang memindahkan titik untuk diletakkan pada vektor.4 Solusi
put_point_on_vec(point, vec)
Jadikan metode sebagai kelas vektor. misalnya
my_vec.put_point(point)
Point
kelas.my_point.put_on_vec(vec)
Vector
mengimplementasikan__call__
, Jadi Anda bisa menggunakannya sepertimy_vec_instance(point)
Ini sebenarnya bagian dari beberapa contoh yang sedang saya kerjakan untuk panduan metode dunder yang dijelaskan dengan Matematika yang akan saya rilis cepat atau lambat.
Saya meninggalkan logika memindahkan poin itu sendiri karena ini bukan tentang pertanyaan ini
sumber