Ketika saya mencoba menggunakan metode statis dari dalam tubuh kelas, dan mendefinisikan metode statis menggunakan staticmethod
fungsi bawaan sebagai dekorator, seperti ini:
class Klass(object):
@staticmethod # use as decorator
def _stat_func():
return 42
_ANS = _stat_func() # call the staticmethod
def method(self):
ret = Klass._stat_func() + Klass._ANS
return ret
Saya mendapatkan kesalahan berikut:
Traceback (most recent call last):<br>
File "call_staticmethod.py", line 1, in <module>
class Klass(object):
File "call_staticmethod.py", line 7, in Klass
_ANS = _stat_func()
TypeError: 'staticmethod' object is not callable
Saya mengerti mengapa hal ini terjadi (penjilidan deskriptor) , dan dapat mengatasinya dengan secara manual mengubahnya _stat_func()
menjadi metode statis setelah penggunaan terakhir, seperti:
class Klass(object):
def _stat_func():
return 42
_ANS = _stat_func() # use the non-staticmethod version
_stat_func = staticmethod(_stat_func) # convert function to a static method
def method(self):
ret = Klass._stat_func() + Klass._ANS
return ret
Jadi pertanyaan saya adalah:
Apakah ada cara yang lebih baik, seperti yang lebih bersih atau lebih "Pythonic", untuk mencapai ini?
python
decorator
static-methods
martineau
sumber
sumber
staticmethod
sama sekali. Mereka biasanya lebih berguna sebagai fungsi tingkat modul, dalam hal ini masalah Anda bukan masalah.classmethod
, di sisi lain ...Jawaban:
staticmethod
objek tampaknya memiliki__func__
atribut yang menyimpan fungsi mentah asli (masuk akal bahwa mereka harus). Jadi ini akan berhasil:Sebagai tambahan, meskipun saya curiga bahwa objek metode statis memiliki semacam atribut yang menyimpan fungsi asli, saya tidak tahu secara spesifik. Dalam semangat mengajar seseorang untuk memancing daripada memberi mereka ikan, inilah yang saya lakukan untuk menyelidiki dan mencari tahu (C&P dari sesi Python saya):
Jenis penggalian yang serupa dalam sesi interaktif (
dir
sangat membantu) seringkali dapat memecahkan pertanyaan semacam ini dengan sangat cepat.sumber
__func__
itu hanya nama lain untukim_func
dan ditambahkan ke Py 2.6 untuk kompatibilitas ke depan Python 3.__func__
Atribut metode statis memberi Anda referensi ke fungsi aslinya, persis seperti jika Anda belum pernah menggunakanstaticmethod
dekorator. Jadi, jika fungsi Anda memerlukan argumen, Anda harus meneruskannya saat memanggil__func__
. Pesan kesalahan Anda terdengar seperti Anda belum memberikan argumen apa pun. Jikastat_func
dalam contoh tulisan ini mengambil dua argumen, Anda akan menggunakan_ANS = stat_func.__func__(arg1, arg2)
stat_func
itu sendiri adalah variabel seperti itu). Apakah maksud Anda Anda tidak dapat menggunakan atribut instance dari kelas yang Anda tetapkan? Itu benar, tetapi tidak mengejutkan; kita tidak memiliki turunan kelas, karena kita masih mendefinisikan kelas! Tetapi bagaimanapun juga, saya hanya memaksudkan mereka sebagai orang yang dapat mempertahankan argumen apa pun yang ingin Anda sampaikan; Anda bisa menggunakan literal di sana.Ini adalah cara yang saya sukai:
Saya lebih suka solusi ini
Klass.stat_func
, karena prinsip KERING . Mengingatkan saya pada alasan mengapa ada yang barusuper()
di Python 3 :)Tapi saya setuju dengan yang lain, biasanya pilihan terbaik adalah mendefinisikan fungsi level modul.
Misalnya dengan
@staticmethod
fungsi, rekursi mungkin tidak terlihat sangat bagus (Anda harus melanggar prinsip KERING dengan memanggil keKlass.stat_func
dalamKlass.stat_func
). Itu karena Anda tidak memiliki referensi keself
metode statis di dalam. Dengan fungsi level modul, semuanya akan terlihat OK.sumber
self.__class__.stat_func()
metode biasa memiliki kelebihan (KERING dan semua itu) daripada menggunakanKlass.stat_func()
, itu tidak benar-benar topik pertanyaan saya - sebenarnya saya menghindari menggunakan yang pertama karena tidak mengaburkan masalah ketidakkonsistenan.self.__class__
lebih baik karena jika subclass menimpastat_func
, makaSubclass.method
akan memanggil subclassstat_func
. Tapi jujur saja, dalam situasi itu jauh lebih baik menggunakan metode nyata daripada statis.Bagaimana dengan menyuntikkan atribut kelas setelah definisi kelas?
sumber
Ini karena metode static menjadi deskriptor dan membutuhkan atribut level kelas untuk menjalankan protokol deskriptor dan mendapatkan callable sejati.
Dari kode sumber:
Tetapi tidak langsung dari dalam kelas saat sedang didefinisikan.
Tetapi seperti disebutkan oleh seorang komentator, ini sebenarnya bukan desain "Pythonic". Cukup gunakan fungsi level modul saja.
sumber
Bagaimana dengan solusi ini? Itu tidak bergantung pada pengetahuan
@staticmethod
implementasi dekorator. Kelas dalam StaticMethod berperan sebagai wadah fungsi inisialisasi statis.sumber
__func__
karena sekarang telah didokumentasikan secara resmi (lihat bagian Perubahan Bahasa Lain dari Apa yang Baru di Python 2.7 dan rujukannya ke Masalah 5982 ). Solusi Anda bahkan lebih portabel, karena mungkin juga akan bekerja dalam versi Python sebelum ke 2.6 (ketika__func__
pertama kali diperkenalkan sebagai sinonim dariim_func
).