Belajar Python , dan memiliki beberapa keraguan mendasar.
1. Saya telah melihat deklarasi variabel (path here) sebagai
class writer:
path = ""
terkadang, tidak ada deklarasi eksplisit tetapi menginisialisasi melalui __init__
.
def __init__(self, name):
self.name = name
Saya memahami tujuan dari __init__
, tetapi disarankan untuk mendeklarasikan variabel di fungsi lain.
2. Bagaimana cara membuat variabel untuk menahan jenis kustom?
class writer:
path = "" # string value
customObj = ??
__name__
atribut memiliki "nama". Tidak semua objek memiliki__name__
atribut, tetapi Anda masih dapat memiliki referensi ke sana. Jika kita mulai menyebut "referensi" sebagai "nama", kita melakukan tindakan merugikan bagi pemula.Jawaban:
Oke, hal pertama yang pertama.
Tidak ada yang namanya "deklarasi variabel" atau "inisialisasi variabel" dalam Python.
Ada yang kita sebut sebagai "penugasan", tapi mungkin sebaiknya kita sebut saja "penamaan".
Penugasan berarti "nama di sisi kiri ini sekarang mengacu pada hasil evaluasi sisi kanan, terlepas dari apa yang dirujuk sebelumnya (jika ada)".
foo = 'bar' # the name 'foo' is now a name for the string 'bar' foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar', # and starts being a name for the integer 6, resulting from the multiplication
Dengan demikian, nama Python (istilah yang lebih baik daripada "variabel", bisa dibilang) tidak memiliki tipe terkait; nilai-nilai itu. Anda dapat menerapkan kembali nama yang sama untuk apa pun apa pun tipenya, tetapi benda tersebut masih memiliki perilaku yang bergantung pada tipenya. Nama hanyalah cara untuk merujuk ke nilai (objek). Ini menjawab pertanyaan kedua Anda: Anda tidak membuat variabel untuk menampung jenis kustom. Anda tidak membuat variabel untuk menampung tipe tertentu. Anda sama sekali tidak "membuat" variabel. Anda memberi nama pada objek.
Poin kedua: Python mengikuti aturan yang sangat sederhana dalam hal kelas, yang sebenarnya jauh lebih konsisten daripada bahasa seperti Java, C ++ dan C #: semua yang dideklarasikan di dalam
class
blok adalah bagian dari kelas . Jadi, fungsi (def
) yang ditulis di sini adalah metode, yaitu bagian dari objek kelas (tidak disimpan pada basis per-instance), seperti di Java, C ++ dan C #; tetapi nama lain di sini juga merupakan bagian dari kelas. Sekali lagi, nama hanyalah nama, dan mereka tidak memiliki tipe terkait, dan fungsi adalah objek juga dalam Python. Jadi:class Example: data = 42 def method(self): pass
Kelas juga merupakan objek , dengan Python.
Jadi sekarang kita telah membuat sebuah objek bernama
Example
, yang mewakili kelas dari semua benda yangExample
s. Objek ini memiliki dua atribut yang disediakan pengguna (Dalam C ++, "anggota"; di C #, "bidang atau properti atau metode"; di Java, "bidang atau metode"). Salah satunya diberi namadata
, dan ini menyimpan nilai integer42
. Yang lainnya diberi namamethod
, dan itu menyimpan objek fungsi. (Ada beberapa atribut lagi yang ditambahkan Python secara otomatis.)Atribut ini masih belum menjadi bagian dari objek. Pada dasarnya, sebuah objek hanyalah sekumpulan lebih banyak nama (nama atribut), sampai Anda turun ke hal-hal yang tidak dapat dibagi lagi. Dengan demikian, nilai dapat dibagikan antara instance kelas yang berbeda, atau bahkan antara objek dari kelas yang berbeda, jika Anda sengaja menyiapkannya.
Mari buat sebuah contoh:
Sekarang kita memiliki objek terpisah bernama
x
, yang merupakan turunan dariExample
. Thedata
danmethod
tidak benar-benar bagian dari objek, tapi kita masih bisa melihat mereka melaluix
karena beberapa keajaiban yang Python dilakukan di belakang layar. Saat kita mencarimethod
, khususnya, kita akan mendapatkan "metode terikat" (saat kita memanggilnya,x
akan diteruskan secara otomatis sebagaiself
parameter, yang tidak dapat terjadi jika kita mencariExample.method
secara langsung).Apa yang terjadi saat kami mencoba menggunakan
x.data
?Saat kami memeriksanya, itu mencari di objek terlebih dahulu. Jika tidak ditemukan di objek, Python mencari di kelas.
Namun, saat kita menugaskan
x.data
, Python akan membuat atribut pada objek tersebut. Ini tidak akan menggantikan atribut kelas '.Ini memungkinkan kita melakukan inisialisasi objek . Python akan secara otomatis memanggil metode kelas
__init__
pada instance baru saat dibuat, jika ada. Dalam metode ini, kita cukup menetapkan ke atribut untuk menetapkan nilai awal atribut itu pada setiap objek:class Example: name = "Ignored" def __init__(self, name): self.name = name # rest as before
Sekarang kita harus menentukan
name
kapan kita membuatExample
, dan setiap instance memiliki sendiriname
. Python akan mengabaikan atribut classExample.name
setiap kali kita mencari.name
dari sebuah instance, karena atribut dari instance tersebut akan ditemukan terlebih dahulu.Satu peringatan terakhir: modifikasi (mutasi) dan penugasan adalah hal yang berbeda!
Di Python, string tidak bisa diubah. Mereka tidak dapat diubah. Saat kamu melakukan:
a = 'hi ' b = a a += 'mom'
Anda tidak mengubah string 'hi' yang asli. Itu tidak mungkin dengan Python. Sebaliknya, Anda membuat string baru
'hi mom'
, dan menyebabkana
berhenti menjadi nama untuk'hi '
, dan mulai menjadi nama untuk'hi mom'
. Kita buatb
nama untuk'hi '
juga, dan setelah di aplikasikan ulanga
,b
masih ada nama untuk'hi '
, karena'hi '
masih ada dan belum diubah.Tetapi daftar dapat diubah:
a = [1, 2, 3] b = a a += [4]
Sekarang
b
[1, 2, 3, 4] juga, karena kita membuatb
nama untuk benda yang samaa
, lalu kita ubah benda itu. Kami tidak membuat daftar baru untuka
nama, karena Python memperlakukan+=
daftar secara berbeda.Ini penting untuk objek karena jika Anda memiliki daftar sebagai atribut kelas, dan menggunakan sebuah instance untuk mengubah daftar, maka perubahan itu akan "terlihat" di semua contoh lainnya. Ini karena (a) data sebenarnya adalah bagian dari objek kelas, dan bukan objek instance apa pun; (b) karena Anda mengubah daftar dan tidak melakukan tugas sederhana, Anda tidak membuat atribut instance baru yang menyembunyikan atribut kelas.
sumber
Ini mungkin terlambat 6 tahun, tetapi dengan Python 3.5 dan yang lebih baru, Anda mendeklarasikan tipe variabel seperti ini:
atau ini:
variable_name # type: shinyType
Jadi dalam kasus Anda (jika Anda memiliki
CustomObject
kelas yang ditentukan), Anda dapat melakukan:Lihat ini atau itu untuk info lebih lanjut.
sumber
a: int
dan kemudian melakukannyaa='hello, world!'
tidak akan gagal, jadi itu tidak menyatakan a menjadi int dan hanya pernah menjadi int. Aku seharusnya mengatakan "itu tidak akan gagal", salahku. Jika Anda melakukannyaa: int
,a='hello, world!'
,a=a+1
maka yang harus gagal di kompilasi dalam bahasa statis diketik.Tidak perlu mendeklarasikan variabel baru dengan Python. Jika kita berbicara tentang variabel dalam fungsi atau modul, tidak diperlukan deklarasi. Hanya memberikan nilai pada nama di mana Anda membutuhkannya:
mymagic = "Magic"
. Variabel dalam Python dapat menyimpan nilai jenis apa pun, dan Anda tidak dapat membatasinya.Pertanyaan Anda secara khusus menanyakan tentang kelas, objek dan variabel instan. Cara idiomatis untuk membuat variabel instance ada di
__init__
metode dan tidak di tempat lain - meskipun Anda dapat membuat variabel instance baru dengan metode lain, atau bahkan dalam kode yang tidak terkait, itu hanya ide yang buruk. Ini akan membuat kode Anda sulit untuk dipikirkan atau dipertahankan.Jadi contohnya:
class Thing(object): def __init__(self, magic): self.magic = magic
Mudah. Sekarang instance kelas ini memiliki
magic
atribut:thingo = Thing("More magic") # thingo.magic is now "More magic"
Membuat variabel di namespace kelas itu sendiri mengarah ke perilaku yang berbeda sama sekali. Ini secara fungsional berbeda, dan Anda hanya boleh melakukannya jika Anda memiliki alasan tertentu. Sebagai contoh:
class Thing(object): magic = "Magic" def __init__(self): pass
Sekarang coba:
thingo = Thing() Thing.magic = 1 # thingo.magic is now 1
Atau:
class Thing(object): magic = ["More", "magic"] def __init__(self): pass thing1 = Thing() thing2 = Thing() thing1.magic.append("here") # thing1.magic AND thing2.magic is now ["More", "magic", "here"]
Ini karena namespace dari kelas itu sendiri berbeda dengan namespace dari objek yang dibuat darinya. Saya akan menyerahkannya kepada Anda untuk menelitinya lebih banyak.
Pesan yang dibawa pulang adalah bahwa idiomatik Python adalah untuk (a) menginisialisasi atribut objek dalam
__init__
metode Anda , dan (b) mendokumentasikan perilaku kelas Anda sesuai kebutuhan. Anda tidak perlu bersusah payah membuat dokumentasi tingkat Sphinx yang lengkap untuk semua yang pernah Anda tulis, tetapi setidaknya beberapa komentar tentang detail apa pun yang mungkin Anda atau orang lain perlukan untuk mengambilnya.sumber
Untuk tujuan pelingkupan, saya menggunakan:
custom_object = None
sumber
Variabel memiliki ruang lingkup, jadi ya itu tepat untuk memiliki variabel yang spesifik untuk fungsi Anda. Anda tidak harus selalu eksplisit tentang definisi mereka; biasanya Anda bisa menggunakannya. Hanya jika Anda ingin melakukan sesuatu yang spesifik untuk jenis variabel, seperti menambahkan untuk daftar, Anda perlu mendefinisikannya sebelum Anda mulai menggunakannya. Contoh tipikal ini.
list = [] for i in stuff: list.append(i)
Ngomong-ngomong, ini sebenarnya bukan cara yang baik untuk menyiapkan daftar. Akan lebih baik untuk mengatakan:
list = [i for i in stuff] # list comprehension
... tapi saya ngelantur.
Pertanyaan Anda yang lain. Objek khusus haruslah kelas itu sendiri.
class CustomObject(): # always capitalize the class name...this is not syntax, just style. pass customObj = CustomObject()
sumber