Konstruktor Python dan __init__

107

Mengapa konstruktor memang disebut "Konstruktor"? Apa tujuan mereka dan apa perbedaannya dengan metode di kelas?

Juga, bisakah ada lebih dari satu __init__di kelas? Saya mencoba yang berikut ini, dapatkah seseorang menjelaskan hasilnya?

>>> class test:
    def __init__(self):
        print "init 1"
    def __init__(self):
        print "init 2"

>>> s=test()
init 2

Terakhir, apakah __init__operator overloader?

Arindam Roychowdhury
sumber
41
Secara teknis, __init__adalah inisial . Konstruktor python adalah __new__. Python menggunakan inisialisasi dua fase otomatis - __new__mengembalikan objek yang valid tetapi (biasanya) tidak berpenghuni (lihat booluntuk contoh kontra), yang kemudian __init__memanggilnya secara otomatis. Ini menghindari masalah yang dimiliki bahasa seperti C ++ dengan objek yang dibuat sebagian - Anda tidak pernah memilikinya di Python (meskipun mungkin diinisialisasi sebagian). Anda hampir tidak perlu mengganti keduanya __new__dan __init__di kelas.
Tim Delaney
2
@TimDelaney: Saya tidak yakin apa yang Anda maksud dengan objek yang dibuat sebagian di C ++.
Sebastian Mach
11
@phresnel Dalam C ++ jenis objek adalah kelas dasar (bukan subkelas) sementara di konstruktor kelas dasar. Anda tidak dapat memanggil metode virtual dalam konstruktor kelas dasar dan meminta subkelas menyediakan implementasinya. Di Java, Anda dapat memanggil metode subclass dalam konstruktor kelas dasar, tetapi variabel anggota subkelas akan secara otomatis diinisialisasi setelah konstruktor kelas dasar (dan pemanggilan metode). Dalam bahasa dengan inisialisasi dua fase seperti Python, Anda dapat dengan senang hati memanggil metode di inisialisasi kelas dasar dan meminta subclass menyediakan (atau mengganti) perilaku tersebut.
Tim Delaney
@TimDelaney: Ah, terima kasih telah mengklarifikasi.
Sebastian Mach
4
@Tokopedia Saya pikir komentar Anda harus menggantikan jawaban yang diterima.
flamenco

Jawaban:

114

Tidak ada fungsi yang berlebihan dalam Python, artinya Anda tidak dapat memiliki banyak fungsi dengan nama yang sama tetapi dengan argumen yang berbeda.

Dalam contoh kode Anda, Anda tidak kelebihan beban __init__() . Apa yang terjadi adalah definisi kedua me - rebinds nama __init__ke metode baru, membuat metode pertama tidak dapat diakses.

Mengenai pertanyaan umum Anda tentang konstruktor, Wikipedia adalah titik awal yang baik. Untuk hal-hal khusus Python, saya sangat merekomendasikan dokumen Python .

NPE
sumber
Apakah ini juga berarti file sumber diurai (diinterpretasikan?) Secara berurutan? Dapatkah saya yakin bahwa fungsi apa pun yang telah saya tetapkan nanti menimpa fungsi yang ditentukan dengan nama yang sama sebelumnya? :( Q saya terdengar konyol .. seharusnya mengetahuinya
0xc0de
4
@ 0xc0de: Dalam Python, definisi fungsi sebenarnya adalah pernyataan yang dapat dieksekusi dan dijalankan dari atas ke bawah, jadi ya.
NPE
1
@ 0xc0de Apa yang sebenarnya terjadi adalah bahwa badan kelas dieksekusi di namespace itu sendiri, namespace itu kemudian diteruskan ke metaclass (di antara dengan nama dan basis). Definisi fungsi kemudian hanya membuat fungsi dengan tubuh yang ditentukan dan menugaskannya ke namanya. Tugas terakhir __init__adalah yang akan berakhir di kelas.
skyking
64

Mengapa konstruktor memang disebut "Konstruktor"?

Konstruktor (bernama __new__) membuat dan mengembalikan instance baru dari kelas. Jadi C.__new__metode kelas adalah konstruktor untuk kelas C.

The C.__init__metode contoh disebut pada contoh tertentu, setelah dibuat, untuk menginisialisasinya sebelum berlalu kembali ke pemanggil. Jadi metode itu adalah penginisialisasi untuk contoh baru C.

Apa perbedaannya dengan metode di kelas?

Seperti yang tercantum dalam dokumentasi resmi __init__ yang disebut setelah instance dibuat . Metode lain tidak menerima perawatan ini.

Apa tujuan mereka?

Tujuan konstruktor C.__new__adalah untuk menentukan perilaku kustom selama konstruksi Cinstance baru .

Tujuan dari penginisialisasi C.__init__adalah untuk menentukan inisialisasi kustom dari setiap instance Csetelah dibuat.

Misalnya Python memungkinkan Anda melakukan:

class Test(object):
    pass

t = Test()

t.x = 10   # here you're building your object t
print t.x

Tetapi jika Anda ingin setiap instance Testmemiliki atribut yang xsama dengan 10, Anda dapat memasukkan kode itu di dalam __init__:

class Test(object):
    def __init__(self):
        self.x = 10

t = Test()
print t.x

Setiap metode instance (metode yang dipanggil pada instance tertentu dari kelas) menerima instance tersebut sebagai argumen pertamanya. Argumen itu dinamai secara konvensional self.

Metode kelas, seperti konstruktor __new__, menerima kelas sebagai argumen pertama mereka.

Sekarang, jika Anda menginginkan nilai khusus untuk xatribut yang harus Anda lakukan adalah meneruskan nilai itu sebagai argumen ke __init__:

class Test(object):
    def __init__(self, x):
        self.x = x

t = Test(10)
print t.x
z = Test(20)
print t.x

Saya harap ini akan membantu Anda menghilangkan beberapa keraguan, dan karena Anda sudah menerima jawaban yang baik untuk pertanyaan lain, saya akan berhenti di sini :)

Rik Poggi
sumber
9

Kelas hanyalah cetak biru untuk membuat objek. Konstruktor adalah beberapa kode yang dijalankan setiap kali Anda membuat objek. Oleh karena itu tidak masuk akal untuk memiliki dua konstruktor. Apa yang terjadi adalah bahwa yang kedua menulis yang pertama.

Apa yang biasanya Anda gunakan untuk membuat variabel untuk objek itu seperti ini:

>>> class testing:
...     def __init__(self, init_value):
...         self.some_value = init_value

Jadi yang dapat Anda lakukan adalah membuat objek dari kelas ini seperti ini:

>>> testobject = testing(5)

Objek uji kemudian akan memiliki objek yang disebut some_valueyang dalam sampel ini akan menjadi 5.

>>> testobject.some_value
5

Tetapi Anda tidak perlu menetapkan nilai untuk setiap objek seperti yang saya lakukan dalam sampel saya. Anda juga bisa melakukan seperti ini:

>>> class testing:
...     def __init__(self):
...         self.some_value = 5

maka nilai some_value akan menjadi 5 dan Anda tidak perlu menyetelnya saat membuat objek.

>>> testobject = testing()
>>> testobject.some_value
5

yang >>> dan ... dalam sampel saya bukanlah apa yang Anda tulis. Ini akan terlihat di pyshell ...

Niclas Nilsson
sumber
Tidak masalah, senang ini membantu Anda :)
Niclas Nilsson
1

coonstructors dipanggil secara otomatis saat Anda membuat objek baru, dengan demikian "membangun" objek. Alasan Anda dapat memiliki lebih dari satu init adalah karena nama hanyalah referensi di python, dan Anda diizinkan untuk mengubah apa yang setiap referensi variabel kapan pun Anda mau (karenanya pengetikan dinamis)

def func(): #now func refers to an empty funcion
    pass
...
func=5      #now func refers to the number 5
def func():
    print "something"    #now func refers to a different function

dalam definisi kelas Anda, itu hanya menyimpan yang terakhir

Ryan Haining
sumber
0

Tidak ada gagasan metode overloading dengan Python. Tapi Anda bisa mencapai efek serupa dengan menentukan argumen opsional dan kata kunci

NLPer
sumber