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'
foo = 2 * 3
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 yang Example
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 nama data
, dan ini menyimpan nilai integer 42
. Yang lainnya diberi nama method
, 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:
x = Example()
Sekarang kita memiliki objek terpisah bernama x
, yang merupakan turunan dari Example
. The data
dan method
tidak benar-benar bagian dari objek, tapi kita masih bisa melihat mereka melalui x
karena beberapa keajaiban yang Python dilakukan di belakang layar. Saat kita mencari method
, khususnya, kita akan mendapatkan "metode terikat" (saat kita memanggilnya, x
akan diteruskan secara otomatis sebagai self
parameter, yang tidak dapat terjadi jika kita mencari Example.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
Sekarang kita harus menentukan name
kapan kita membuat Example
, dan setiap instance memiliki sendiri name
. Python akan mengabaikan atribut class Example.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 menyebabkan a
berhenti menjadi nama untuk 'hi '
, dan mulai menjadi nama untuk 'hi mom'
. Kita buat b
nama untuk 'hi '
juga, dan setelah di aplikasikan ulang a
, 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 membuat b
nama untuk benda yang sama a
, lalu kita ubah benda itu. Kami tidak membuat daftar baru untuk a
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.