Apa yang __init__ dan self lakukan pada Python?

794

Saya belajar bahasa pemrograman Python dan saya menemukan sesuatu yang saya tidak sepenuhnya mengerti.

Dalam metode seperti:

def method(self, blah):
    def __init__(?):
        ....
    ....

Apa yang selfharus dilakukan Apa artinya itu? Apakah ini wajib?

Apa yang dilakukan __init__metode ini? Mengapa itu perlu? (dll.)

Saya pikir mereka mungkin konstruksi OOP, tapi saya tidak tahu banyak.

ivanleoncz
sumber

Jawaban:

585

Dalam kode ini:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... selfvariabel mewakili turunan dari objek itu sendiri. Sebagian besar bahasa berorientasi objek melewatkan ini sebagai parameter tersembunyi ke metode yang didefinisikan pada objek; Python tidak. Anda harus mendeklarasikannya secara eksplisit. Saat Anda membuat instance Akelas dan memanggil metode-metodenya, itu akan diteruskan secara otomatis, seperti di ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

The __init__Metode kira-kira apa yang mewakili konstruktor di Python. Saat Anda memanggil A()Python membuat objek untuk Anda, dan meneruskannya sebagai parameter pertama ke __init__metode. Parameter tambahan apa pun (misalnya, A(24, 'Hello')) juga akan dilewatkan sebagai argumen - dalam hal ini menyebabkan pengecualian muncul, karena konstruktor tidak mengharapkannya.

Chris B.
sumber
8
bagaimana jika Anda menempatkan init dix = 'Hello' luar tetapi di dalam kelas? apakah itu seperti java di mana itu sama, atau apakah itu menjadi seperti variabel statis yang hanya diinisialisasi sekali?
Jayen
15
Ini seperti variabel statis. Ini hanya diinisialisasi sekali, dan tersedia melalui A.xatau a.x. Perhatikan bahwa utama itu pada kelas tertentu tidak akan mempengaruhi dasar, sehingga A.x = 'foo'; a.x = 'bar'; print a.x; print A.xakan mencetak barkemudianfoo
Chris B.
156
Patut ditunjukkan bahwa argumen pertama tidak perlu disebut self, hanya dengan konvensi.
Henry Gomersall
13
Apa gunanya objectdeklarasi kelas? Saya perhatikan beberapa kelas memiliki ini dan beberapa tidak
Chris
9
@ Chris Ini untuk kompatibilitas Python 2. Dalam Python 3 tidak perlu mewarisi secara eksplisit objectkarena itu terjadi secara default.
Gabriel
241

Yap, Anda benar, ini adalah konstruksi oop.

__init__adalah konstruktor untuk suatu kelas. The selfparameter mengacu pada contoh objek (seperti thisdi C ++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

The __init__Metode dipanggil ketika memori untuk objek dialokasikan:

x = Point(1,2)

Penting untuk menggunakan selfparameter di dalam metode objek jika Anda ingin mempertahankan nilai dengan objek. Jika, misalnya, Anda menerapkan __init__metode seperti ini:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Parameter Anda xdan yakan disimpan dalam variabel di stack dan akan dibuang ketika metode init keluar dari ruang lingkup. Mengatur variabel-variabel itu sebagai self._xdan self._ymenetapkan variabel-variabel tersebut sebagai anggota Pointobjek (dapat diakses selama masa objek).

RedBlueThing
sumber
1
Jadi, adakah alasan mengapa Anda tidak ingin selfberada di konstruktor? Mengapa Anda bahkan harus menentukannya, bukankah akan lebih baik jika itu tersirat?
Aaron Franke
Sejauh yang saya tahu, __ init __ bukan konstruktor, ini adalah metode pertama yang akan dieksekusi ketika ada objek yang dibuat, __ init __ digunakan untuk mengatur objek. __ baru __ adalah konstruktor dalam python.
Deepanshu
206

Contoh ilustrasi singkat

Dengan harapan ini mungkin sedikit membantu, inilah contoh sederhana yang saya gunakan untuk memahami perbedaan antara variabel yang dideklarasikan di dalam kelas, dan variabel yang dideklarasikan di dalam suatu __init__fungsi:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

Keluaran:

345
123
Dave Everitt
sumber
7
Pengamatan menarik tapi saya pikir Anda berada di jalur yang salah. Dengan print MyClass.i, sepertinya Anda memanggil variabel 'statis' i. Sedangkan dengan ai Anda memanggil variabel anggota, i. Tampak bagi saya bahwa init hanyalah konstruktor yang pertama kali dieksekusi ketika Anda membuat objek kelas.
captainspi
34
Itulah yang saya coba 'jelaskan pada diri saya' dengan contoh ini - bahwa variabel yang ditetapkan __init__adalah apa yang diteruskan ke instance kelas, bukan variabel 'statis' dari kelas itu sendiri yang memiliki nama yang sama ...
Dave Everitt
44

Pendeknya:

  1. self seperti yang disarankan, mengacu pada dirinya sendiri - objek yang disebut metode. Artinya, jika Anda memiliki objek N memanggil metode, maka self.aakan merujuk ke contoh terpisah dari variabel untuk masing-masing objek N. Bayangkan N salinan variabel auntuk setiap objek
  2. __init__adalah apa yang disebut sebagai konstruktor dalam bahasa OOP lainnya seperti C ++ / Java. Ide dasarnya adalah bahwa itu adalah metode khusus yang secara otomatis dipanggil ketika objek Kelas itu dibuat
Acumenus
sumber
29

__init__tidak bertindak seperti konstruktor. Anda harus meneruskan "diri" ke fungsi kelas apa pun sebagai argumen pertama jika Anda ingin mereka berperilaku sebagai metode non-statis. "Diri" adalah variabel instan untuk kelas Anda.

ewalk
sumber
1
'diri' mendefinisikan apakah suatu metode statis atau tidak! Wow, itu pembuka mata untuk orang Jawa ini.
liwevire
25

Coba kode ini. Semoga ini membantu banyak programmer C seperti saya untuk Belajar Py.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Keluaran:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

Kode Jayz
sumber
Saya tidak tahu apakah ini hanya saya, tetapi membaca kode ini sedikit membingungkan. Mungkin itu karena saya masih seorang programmer Python pemula, idk.
Linny
Saya tidak jelas tentang hal doc .. apakah itu menarik dokumentasi? dan jika saya melakukan: '' 'test - my doc' ', dapatkah saya menggunakan: print.p .__ test__? atau apakah doc kata kunci tertentu?
Thomas
@ Thomas doc adalah kata kunci untuk detail yang terdokumentasi. Kutipan rangkap tiga digunakan untuk menuliskan dokumen dan dokumen adalah entitas opsional.
Jayzcode
25

Objek kelas mendukung dua jenis operasi: referensi atribut dan instantiasi

Referensi atribut menggunakan sintaksis standar yang digunakan untuk semua referensi atribut dengan Python: obj.name. Nama atribut yang valid adalah semua nama yang ada di namespace kelas ketika objek kelas dibuat. Jadi, jika definisi kelas tampak seperti ini:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

kemudian MyClass.idan MyClass.fadalah referensi atribut yang valid, masing-masing mengembalikan integer dan fungsi objek. Atribut kelas juga dapat ditetapkan, sehingga Anda dapat mengubah nilai MyClass.iberdasarkan penugasan. __doc__juga merupakan atribut yang valid, mengembalikan docstring milik kelas: "Kelas contoh sederhana".

Instansiasi kelas menggunakan notasi fungsi. Hanya berpura-pura bahwa objek kelas adalah fungsi tanpa parameter yang mengembalikan instance baru dari kelas. Sebagai contoh:

x = MyClass()

The Instansiasi Operasi ( “memanggil” objek kelas) menciptakan objek kosong. Banyak kelas suka membuat objek dengan instance yang disesuaikan dengan kondisi awal tertentu. Oleh karena itu kelas dapat mendefinisikan metode khusus yang dinamai __init__(), seperti ini:

def __init__(self):
    self.data = []

Ketika sebuah kelas mendefinisikan sebuah __init__()metode, instantiasi kelas secara otomatis memanggil __init__()instance kelas yang baru dibuat. Jadi dalam contoh ini, contoh baru yang diinisialisasi dapat diperoleh dengan:

x = MyClass()

Tentu saja, __init__()metode ini mungkin memiliki argumen untuk fleksibilitas yang lebih besar. Dalam hal itu, argumen yang diberikan kepada operator instantiasi kelas diteruskan ke __init__(). Sebagai contoh,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Diambil dari dokumentasi resmi yang paling membantu saya pada akhirnya.


Ini contoh saya

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

Saat Anda membuat instance dari tagihan kelas:

purchase = Bill(5,6,7)

Anda mendapatkan:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)
Harvey
sumber
22

Kesulitan memahami ini sendiri. Bahkan setelah membaca jawabannya di sini.

Untuk memahami __init__metode ini, Anda perlu memahami diri sendiri.

Parameter diri

Argumen yang diterima oleh __init__metode ini adalah:

def __init__(self, arg1, arg2):

Tapi kami hanya benar-benar memberikan dua argumen:

instance = OurClass('arg1', 'arg2')

Dari mana datangnya argumen tambahan?

Ketika kita mengakses atribut dari suatu objek, kita melakukannya dengan nama (atau dengan referensi). Di sini instance adalah referensi ke objek baru kami. Kami mengakses metode printargs dari objek instance menggunakan instance.printargs.

Untuk mengakses atribut objek dari dalam __init__metode, kita perlu referensi ke objek.

Setiap kali suatu metode dipanggil, referensi ke objek utama dilewatkan sebagai argumen pertama. Dengan konvensi, Anda selalu menyebut argumen pertama ini untuk metode Anda sendiri.

Ini berarti dalam __init__metode yang dapat kita lakukan:

self.arg1 = arg1
self.arg2 = arg2

Di sini kita mengatur atribut pada objek. Anda dapat memverifikasi ini dengan melakukan hal berikut:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

nilai-nilai seperti ini dikenal sebagai atribut objek. Di sini __init__metode menetapkan atribut arg1 dan arg2 dari instance.

sumber: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

eee
sumber
17

perhatikan bahwa selfsebenarnya bisa berupa pengidentifikasi python yang valid. Sebagai contoh, kita dapat dengan mudah menulis, dari contoh Chris B:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

dan itu akan bekerja sama persis. Namun disarankan untuk menggunakan diri sendiri karena pythoner lain akan mengenalinya lebih mudah.

SingleNegationElimination
sumber
Saya setuju bahwa diri akan direkomendasikan sebagai pengganti foo, membantu programmer lain dengan melihat kode
Linny
15

Pada dasarnya, Anda perlu menggunakan kata kunci 'mandiri' saat menggunakan variabel dalam berbagai fungsi dalam kelas yang sama. Sedangkan untuk init , ini digunakan untuk mengatur nilai-nilai default jika tidak ada fungsi lain dari dalam kelas yang dipanggil.

pengguna1675111
sumber
6
Tidak ada kata kunci 'sendiri' di Python. Memanggil parameter pertama 'diri' hanyalah sebuah konvensi.
David Anderson
diri pada dasarnya digunakan sebagai pengganti. Anda tidak perlu menggunakan sendiri, Anda bisa menggunakan "eeee" atau "foo" atau yang lainnya, hanya disarankan untuk programmer lain saat membaca kode Anda
Linny
15
  1. __init__pada dasarnya adalah fungsi yang akan "menginisialisasi" / "mengaktifkan" properti kelas untuk objek tertentu, setelah dibuat dan dicocokkan dengan kelas yang sesuai ..
  2. self mewakili objek yang akan mewarisi properti tersebut.
atlas
sumber
1
kata kunci "mandiri" tidak harus digunakan, itu hanya pengganti. Anda dapat menggunakan kata apa pun, tetapi disarankan agar Anda menggunakan sendiri untuk membantu keterbacaan program
Linny
13

'Diri' adalah referensi ke instance kelas

class foo:
    def bar(self):
            print "hi"

Sekarang kita dapat membuat instance dari foo dan memanggil metode di atasnya, parameter self ditambahkan oleh Python dalam kasus ini:

f = foo()
f.bar()

Tetapi itu dapat diteruskan juga jika pemanggilan metode tidak dalam konteks turunan kelas, kode di bawah ini melakukan hal yang sama

f = foo()
foo.bar(f)

Menariknya nama variabel 'diri' hanyalah sebuah konvensi. Definisi di bawah ini akan bekerja persis sama. Setelah mengatakan bahwa itu adalah konvensi yang sangat kuat yang harus diikuti selalu , tetapi ia mengatakan sesuatu tentang sifat fleksibel bahasa

class foo:
    def bar(s):
            print "hi"
menodai
sumber
Mengapa itu mengatakan sesuatu tentang sifat fleksibel bahasa? Itu hanya mengatakan Anda dapat memberikan variabel nama hukum apa pun yang Anda pilih. Bagaimana itu berbeda dari bahasa pemrograman lain?
Daniel
Seperti yang saya tulis dalam jawaban saya "bar" hanyalah sebuah fungsi di mana instance kelas disediakan sebagai parameter pertama. Jadi sementara "bar" didefinisikan sebagai metode yang terikat ke "foo" itu juga bisa disebut dengan turunan dari beberapa kelas lain. Ini bukan bagaimana metode dan "ini" bekerja di Jawa misalnya, meskipun saya membayangkan Anda melihat bahwa ini adalah konsep yang sama, fungsi dan beberapa konteks contoh (konteks contoh menjadi parameter pertama dalam Python dan "ini" di Jawa ") Mungkin sekarang Anda dapat melihat fleksibilitas bahasa yang saya maksud?
tarn
Ya itu menunjukkan fleksibilitas bahasa. Cara Anda mengutarakan jawaban Anda, sepertinya Anda mengatakan bahwa fakta bahwa Anda dapat memanggil variabel "diri" sesuatu yang lain (seperti s) menunjukkan fleksibilitas python.
Daniel
12

Hanya demo untuk pertanyaan itu.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
debug
sumber
11

Dalam kode ini:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

Di sini __init__bertindak sebagai konstruktor untuk kelas dan ketika suatu objek dipakai, fungsi ini disebut. selfmewakili objek instantiating.

c = Cat('Kitty')
c.info()

Hasil dari pernyataan di atas adalah sebagai berikut:

I am a cat and I am called Kitty
Anagha
sumber
11

Apa yang dilakukan sendiri ? Apa artinya itu ? Apakah ini wajib ?

Argumen pertama dari setiap metode kelas, termasuk init, selalu merupakan referensi ke instance kelas saat ini . Dengan konvensi, argumen ini selalu dinamai self. Dalam metode init, selfmerujuk ke objek yang baru dibuat; dalam metode kelas lain, ini merujuk pada instance yang metodenya dipanggil.

Python tidak memaksa Anda untuk menggunakan " diri ". Anda dapat memberikan nama apa saja yang Anda inginkan. Tapi ingat argumen pertama dalam definisi metode adalah referensi ke objek . Python menambahkan selfargumen ke daftar untuk Anda; Anda tidak perlu memasukkannya saat Anda memanggil metode. jika Anda tidak menyediakan metode init sendiri maka Anda akan mendapatkan kesalahan

TypeError: __init___() takes no arguments (1 given)

Apa yang dilakukan metode init ? Mengapa itu perlu? (dll.)

initkependekan dari inisialisasi. Ini adalah konstruktor yang dipanggil ketika Anda membuat instance kelas dan itu tidak perlu . Tapi biasanya itu praktik kami untuk menulis metode init untuk menetapkan keadaan default objek. Jika Anda tidak ingin mengatur keadaan objek pada awalnya maka Anda tidak perlu menulis metode ini.

Muhammad Faizan Khan
sumber
8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()
Manohar Reddy Poreddy
sumber
5

Python __init__dan selfapa yang mereka lakukan?

Apa yang self harus dilakukan Apa artinya itu? Apakah ini wajib?

Apa yang dilakukan __init__metode ini? Mengapa itu perlu? (dll.)

Contoh yang diberikan tidak benar, jadi izinkan saya membuat contoh yang benar berdasarkan itu:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

Ketika kita membuat instance objek, __init__dipanggil untuk mengkustomisasi objek setelah objek dibuat. Artinya, ketika kita sebut SomeObjectdengan 'blah'di bawah ini (yang bisa apa saja), hal itu akan diteruskan ke __init__fungsi sebagai argumen, blah:

an_object = SomeObject('blah')

The selfargumen adalah contoh SomeObjectyang akan ditugaskan untuk an_object.

Kemudian, kita mungkin ingin memanggil metode pada objek ini:

an_object.method()

Melakukan pencarian putus-putus, yaitu, an_object.method , mengikat instance ke instance fungsi, dan metode (seperti disebut di atas) sekarang menjadi metode "terikat" - yang berarti kita tidak perlu secara eksplisit meneruskan instance ke pemanggilan metode. .

Pemanggilan metode mendapatkan instance karena terikat pada pencarian putus-putus, dan ketika dipanggil, maka jalankan kode apa pun yang diprogram untuk dijalankan.

selfArgumen yang disahkan secara implisit disebut selfdengan konvensi. Kami bisa menggunakan nama Python legal lainnya, tetapi Anda mungkin akan mendapatkan tar dan bulu oleh programmer Python lain jika Anda mengubahnya ke sesuatu yang lain.

__init__adalah metode khusus, yang didokumentasikan dalam dokumentasi datamodel Python . Ini dipanggil segera setelah instance dibuat (biasanya via __new__- meskipun __new__tidak diperlukan kecuali Anda mensubklasifikasikan datatype yang tidak dapat diubah).

Aaron Hall
sumber
3

Di sini, pria itu telah menulis dengan cukup baik dan sederhana: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-python-classes-and-object-oriented-programming/

Baca tautan di atas sebagai referensi untuk ini:

self? Jadi ada apa dengan parameter mandiri itu untuk semua metode Pelanggan? Apa itu? Tentu saja itu contohnya! Dengan kata lain, metode seperti penarikan mendefinisikan instruksi untuk menarik uang dari beberapa akun pelanggan abstrak. Memanggil jeff.withdraw (100.0) menempatkan instruksi tersebut untuk digunakan pada instance jeff.

Jadi ketika kami mengatakan def withdraw (mandiri, jumlah) :, kami mengatakan, "Inilah cara Anda menarik uang dari objek Pelanggan (yang akan kami sebut mandiri) dan angka dolar (yang akan kami sebut jumlah). adalah contoh dari Pelanggan yang menarik sedang dipanggil. Itu bukan saya membuat analogi, baik. jeff.withdraw (100.0) hanya singkatan untuk Customer.withdraw (jeff, 100.0), yang sangat valid (jika tidak sering terlihat) kode.

init self mungkin masuk akal untuk metode lain, tetapi bagaimana dengan init ? Ketika kita memanggil init , kita sedang dalam proses membuat objek, jadi bagaimana mungkin sudah ada diri? Python memungkinkan kita untuk memperluas pola diri ketika objek dibangun juga, meskipun itu tidak pas. Bayangkan saja jeff = Pelanggan ('Jeff Knupp', 1000.0) sama dengan memanggil jeff = Pelanggan (jeff, 'Jeff Knupp', 1000.0); jeff yang dilewati juga menghasilkan hasilnya.

Inilah sebabnya mengapa ketika kita memanggil init , kita menginisialisasi objek dengan mengatakan hal-hal seperti self.name = name. Ingat, karena diri adalah contohnya, ini sama dengan mengatakan jeff.name = name, yang sama dengan jeff.name = 'Jeff Knupp. Demikian pula, self.balance = keseimbangan sama dengan jeff.balance = 1000.0. Setelah dua baris ini, kami menganggap objek Pelanggan "diinisialisasi" dan siap digunakan.

Hati-hati denganmu __init__

Setelah init selesai, penelepon dapat dengan tepat mengasumsikan bahwa objek siap digunakan. Yaitu, setelah jeff = Pelanggan ('Jeff Knupp', 1000.0), kita dapat mulai melakukan setoran dan menarik panggilan pada jeff; jeff adalah objek yang diinisialisasi penuh.

Laxmikant
sumber