Saya mengajar diri saya sendiri Python dan pelajaran saya yang terbaru adalah bahwa Python bukan Java , jadi saya baru saja menghabiskan waktu mengubah semua metode Kelas saya menjadi fungsi.
Saya sekarang menyadari bahwa saya tidak perlu menggunakan metode Kelas untuk apa yang akan saya lakukan dengan static
metode di Jawa, tapi sekarang saya tidak yakin kapan saya akan menggunakannya. Semua saran yang dapat saya temukan tentang metode Kelas Python adalah sepanjang jalur pemula seperti saya harus menghindari mereka, dan dokumentasi standar paling buram ketika membahasnya.
Adakah yang punya contoh yang baik menggunakan metode Kelas dalam Python atau setidaknya seseorang dapat memberi tahu saya ketika metode Kelas dapat digunakan secara masuk akal?
sumber
obj.cls_mthd(...)
atautype(obj).cls_mthd(...)
?Metode pabrik (konstruktor alternatif) memang merupakan contoh klasik dari metode kelas.
Pada dasarnya, metode kelas cocok kapan saja Anda ingin memiliki metode yang secara alami cocok dengan namespace kelas, tetapi tidak terkait dengan instance kelas tertentu.
Sebagai contoh, dalam modul unipath yang sangat baik :
Direktori saat ini
Path.cwd()
Path("/tmp/my_temp_dir")
,. Ini adalah metode kelas..chdir()
Karena direktori saat ini adalah proses yang luas,
cwd
metode ini tidak memiliki instance khusus yang harus dikaitkan. Namun, mengubahcwd
ke direktoriPath
instance yang diberikan memang harus menjadi metode instance.Hmmm ... karena
Path.cwd()
memang mengembalikanPath
contoh, saya kira itu bisa dianggap sebagai metode pabrik ...sumber
Pikirkan seperti ini: metode normal berguna untuk menyembunyikan detail pengiriman: Anda bisa mengetik
myobj.foo()
tanpa khawatir tentang apakahfoo()
metode ini diterapkan oleh kelasmyobj
objek atau salah satu kelas induknya. Metode kelas persis analog dengan ini, tetapi dengan objek kelas sebagai gantinya: mereka membiarkan Anda meneleponMyClass.foo()
tanpa harus khawatir apakahfoo()
diimplementasikan secara khusus olehMyClass
karena diperlukan versi khusus sendiri, atau apakah itu membiarkan kelas induknya menangani panggilan.Metode kelas sangat penting ketika Anda melakukan pengaturan atau perhitungan yang mendahului pembuatan instance aktual, karena sampai instance ada Anda jelas tidak dapat menggunakan instance sebagai titik pengiriman untuk panggilan metode Anda. Contoh yang baik dapat dilihat dalam kode sumber SQLAlchemy; lihat
dbapi()
metode kelas di tautan berikut:https://github.com/zzzeek/sqlalchemy/blob/ab6946769742602e40fb9ed9dde5f642885d1906/lib/sqlalchemy/dialects/mssql/pymssql.py#L47
Anda dapat melihat bahwa
dbapi()
metode, yang digunakan backend basis data untuk mengimpor pustaka database khusus vendor yang dibutuhkan sesuai permintaan, adalah metode kelas karena itu perlu dijalankan sebelum instance koneksi database tertentu mulai dibuat - tetapi tidak bisa menjadi fungsi sederhana atau fungsi statis, karena mereka ingin dapat memanggil metode lain yang mendukung yang mungkin juga perlu ditulis lebih khusus dalam subkelas daripada di kelas induknya. Dan jika Anda mengirim ke suatu fungsi atau kelas statis, maka Anda "lupa" dan kehilangan pengetahuan tentang kelas mana yang melakukan inisialisasi.sumber
Baru-baru ini saya menginginkan kelas logging yang sangat ringan yang akan menghasilkan jumlah output yang bervariasi tergantung pada level logging yang dapat diatur secara programatis. Tapi saya tidak ingin membuat instance kelas setiap kali saya ingin menampilkan pesan debugging atau kesalahan atau peringatan. Tetapi saya juga ingin merangkum fungsi dari fasilitas logging ini dan membuatnya dapat digunakan kembali tanpa pernyataan global.
Jadi saya menggunakan variabel kelas dan
@classmethod
dekorator untuk mencapai ini.Dengan kelas Logging sederhana saya, saya bisa melakukan hal berikut:
Kemudian, dalam kode saya, jika saya ingin mengeluarkan banyak informasi debug, saya hanya perlu kode
Kesalahan bisa diatasi
Dalam lingkungan "produksi", saya dapat menentukan
dan sekarang, hanya pesan kesalahan yang akan ditampilkan. Pesan debug tidak akan dicetak.
Inilah kelas saya:
Dan beberapa kode yang mengujinya sedikit saja:
sumber
Konstruktor alternatif adalah contoh klasik.
sumber
Ketika pengguna masuk di situs web saya, objek Pengguna () dipakai dari nama pengguna dan kata sandi.
Jika saya memerlukan objek pengguna tanpa pengguna berada di sana untuk login (mis. Pengguna admin mungkin ingin menghapus akun pengguna lain, jadi saya perlu instantiate pengguna itu dan memanggil metode hapusnya):
Saya memiliki metode kelas untuk mengambil objek pengguna.
sumber
Saya pikir jawaban yang paling jelas adalah jawaban AmanKow . Itu bermuara pada bagaimana Anda ingin mengatur kode Anda. Anda dapat menulis semuanya sebagai fungsi level modul yang dibungkus dalam namespace dari modul yaitu
Kode prosedural di atas tidak terorganisir dengan baik, seperti yang Anda lihat setelah hanya 3 modul yang membingungkan, apa yang dilakukan masing-masing metode? Anda dapat menggunakan nama deskriptif panjang untuk fungsi (seperti di java) tetapi kode Anda tetap tidak dapat dikelola dengan sangat cepat.
Cara berorientasi objek adalah memecah kode Anda menjadi blok yang dapat dikelola yaitu Kelas & objek dan fungsi dapat dikaitkan dengan instance objek atau dengan kelas.
Dengan fungsi-fungsi kelas, Anda memperoleh level pembagian lain dalam kode Anda dibandingkan dengan fungsi-fungsi level modul. Jadi, Anda bisa mengelompokkan fungsi terkait dalam kelas untuk membuatnya lebih spesifik untuk tugas yang Anda tetapkan untuk kelas itu. Misalnya Anda dapat membuat kelas utilitas file:
Dengan cara ini lebih fleksibel dan lebih mudah dikelola, Anda mengelompokkan fungsi bersama dan lebih jelas dengan apa yang dilakukan masing-masing fungsi. Anda juga mencegah konflik nama, misalnya salinan fungsi mungkin ada di modul impor lainnya (misalnya salinan jaringan) yang Anda gunakan dalam kode Anda, jadi ketika Anda menggunakan nama lengkap FileUtil.copy () Anda menghapus masalah dan kedua fungsi salin dapat digunakan berdampingan.
sumber
FileUtil
metode kelas sebagai fungsi darifile_util
modul, itu akan sebanding dan tidak menyalahgunakan OOP ketika tidak ada objek yang sebenarnya (sebenarnya Anda bisa berpendapat itu lebih disukai, karena Anda tidak berakhir denganfrom file_util import FileUtil
kata kerja lain). Konflik nama juga dapat dihindari dalam kode prosedural dengan melakukanimport file_util
alih - alihfrom file_util import ...
.Secara jujur? Saya tidak pernah menemukan penggunaan untuk staticmethod atau classmethod. Saya belum melihat operasi yang tidak dapat dilakukan menggunakan fungsi global atau metode instance.
Akan berbeda jika python menggunakan anggota pribadi dan dilindungi lebih seperti Java. Di Jawa, saya memerlukan metode statis untuk dapat mengakses anggota pribadi instance untuk melakukan hal-hal. Dalam Python, itu jarang diperlukan.
Biasanya, saya melihat orang menggunakan staticmethods dan classmethods ketika semua yang benar-benar perlu mereka lakukan adalah menggunakan ruang nama modul-tingkat python lebih baik.
sumber
Ini memungkinkan Anda untuk menulis metode kelas generik yang dapat Anda gunakan dengan kelas yang kompatibel.
Sebagai contoh:
Jika Anda tidak menggunakan,
@classmethod
Anda dapat melakukannya dengan kata kunci sendiri tetapi membutuhkan turunan Kelas:sumber
Saya dulu bekerja dengan PHP dan baru-baru ini saya bertanya pada diri sendiri, apa yang terjadi dengan metode kelas ini? Manual Python sangat teknis dan sangat pendek dalam kata-kata sehingga tidak akan membantu dengan memahami fitur itu. Saya telah googling dan googling dan saya menemukan jawaban -> http://code.anjanesh.net/2007/12/python-classmethods.html .
Jika Anda malas mengkliknya. Penjelasan saya lebih pendek dan di bawah. :)
dalam PHP (mungkin tidak semua dari Anda tahu PHP, tetapi bahasa ini sangat jelas sehingga semua orang harus mengerti apa yang saya bicarakan) kami memiliki variabel statis seperti ini:
Outputnya akan dalam kedua kasus 20.
Namun dalam python kita dapat menambahkan dekorator @classmethod dan dengan demikian dimungkinkan untuk memiliki output 10 dan 20 masing-masing. Contoh:
Pintar, bukan?
sumber
B.setInnerVar(20)
dibiarkan, itu akan mencetak10
dua kali (daripada memberikan kesalahan pada panggilan echoInnerBar kedua) yang tidakinner_var
didefinisikan.Metode kelas menyediakan "gula semantik" (tidak tahu apakah istilah ini banyak digunakan) - atau "kenyamanan semantik".
Contoh: Anda mendapat satu set kelas yang mewakili objek. Anda mungkin ingin memiliki metode kelas
all()
ataufind()
menulisUser.all()
atauUser.find(firstname='Guido')
. Itu bisa dilakukan menggunakan fungsi level modul tentu saja ...sumber
Apa yang baru saja mengenai saya, yang berasal dari Ruby, adalah bahwa apa yang disebut metode kelas dan apa yang disebut metode instan hanyalah sebuah fungsi dengan makna semantik yang diterapkan pada parameter pertamanya, yang diam-diam diteruskan ketika fungsi tersebut disebut sebagai metode sebuah objek (mis
obj.meth()
).Biasanya objek itu harus berupa instance tetapi
@classmethod
dekorator metode mengubah aturan untuk lulus kelas. Anda dapat memanggil metode kelas dengan instance (hanya fungsi) - argumen pertama adalah kelasnya.Karena itu hanya fungsi , itu hanya dapat dideklarasikan sekali dalam ruang lingkup yang diberikan (yaitu
class
definisi). Karena itu, jika mengikuti, sebagai kejutan bagi seorang Rubyist, bahwa Anda tidak dapat memiliki metode kelas dan metode contoh dengan nama yang sama .Pertimbangkan ini:
Anda dapat memanggil
foo
sebuah instanceTapi tidak di kelas:
Sekarang tambahkan
@classmethod
:Memanggil instance sekarang melewati kelasnya:
seperti halnya memanggil kelas:
Hanya konvensi yang menentukan yang kami gunakan
self
untuk argumen pertama tentang metode instance dancls
metode kelas. Saya tidak menggunakan di sini untuk menggambarkan bahwa itu hanya argumen. Di Ruby,self
adalah kata kunci.Kontras dengan Ruby:
Metode kelas Python hanyalah fungsi yang didekorasi dan Anda dapat menggunakan teknik yang sama untuk membuat dekorator Anda sendiri . Metode yang dihiasi membungkus metode nyata (dalam kasus
@classmethod
itu melewati argumen kelas tambahan). Metode yang mendasarinya masih ada, tersembunyi tetapi masih dapat diakses .catatan kaki: Saya menulis ini setelah bentrokan nama antara kelas dan metode contoh membuat saya penasaran. Saya jauh dari ahli Python dan ingin komentar jika semua ini salah.
sumber
super()
). AFICT, "keajaiban" terjadi ketika atribut diatur atau dibaca. Panggilanobj.meth(arg)
dengan Python (tidak seperti Ruby) berarti sederhana(obj.meth)(arg)
. Tidak ada yang diam-diam berlalu di mana saja,obj.meth
hanya objek yang bisa dipanggil yang menerima satu argumen kurang dari fungsi yang dibuatnya.obj.meth
, pada gilirannya, berarti sederhanagetattr(obj, "meth")
.Ini adalah topik yang menarik. Menurut saya adalah bahwa metode python beroperasi seperti singleton daripada pabrik (yang menghasilkan instance kelas). Alasannya adalah singleton adalah bahwa ada objek umum yang diproduksi (kamus) tetapi hanya sekali untuk kelas tetapi dibagikan oleh semua contoh.
Untuk menggambarkan ini di sini adalah contohnya. Perhatikan bahwa semua instance memiliki referensi ke kamus tunggal. Ini bukan pola pabrik seperti yang saya mengerti. Ini mungkin sangat unik untuk python.
sumber
Saya bertanya pada diri sendiri pertanyaan yang sama beberapa kali. Dan meskipun orang-orang di sini berusaha keras untuk menjelaskannya, IMHO jawaban terbaik (dan paling sederhana) jawaban yang saya temukan adalah deskripsi metode Kelas dalam Dokumentasi Python.
Ada juga referensi ke metode Statis. Dan jika seseorang sudah tahu metode contoh (yang saya asumsikan), jawaban ini mungkin merupakan bagian terakhir untuk menyatukan semuanya ...
Elaborasi lebih lanjut dan lebih dalam tentang topik ini dapat ditemukan juga di dokumentasi: Hirarki jenis standar (gulir ke bawah ke bagian Metode instan)
sumber
@classmethod
dapat berguna untuk dengan mudah membuat instance objek kelas itu dari sumber daya luar. Pertimbangkan yang berikut ini:Kemudian di file lain:
Mengakses inst.x akan memberikan nilai yang sama dengan pengaturan ['x'].
sumber
Kelas mendefinisikan satu set instance, tentu saja. Dan metode kelas bekerja pada instance individual. Metode kelas (dan variabel) tempat untuk menggantung informasi lain yang terkait dengan set instance atas semua.
Sebagai contoh jika kelas Anda mendefinisikan satu set siswa, Anda mungkin ingin variabel kelas atau metode yang mendefinisikan hal-hal seperti set kelas yang siswa dapat menjadi anggota.
Anda juga dapat menggunakan metode kelas untuk mendefinisikan alat untuk bekerja di seluruh set. Misalnya Student.all_of_em () mungkin mengembalikan semua siswa yang dikenal. Jelas jika set instance Anda memiliki lebih banyak struktur daripada hanya set, Anda dapat memberikan metode kelas untuk mengetahui tentang struktur itu. Students.all_of_em (grade = 'junior')
Teknik seperti ini cenderung mengarah pada menyimpan anggota dari set instance ke dalam struktur data yang berakar pada variabel kelas. Anda harus berhati-hati untuk menghindari frustrasi pengumpulan sampah itu.
sumber