Pertanyaan Apa tujuan dari diri sendiri?


Apa tujuan dari self kata dengan Python? Saya mengerti itu merujuk pada objek spesifik yang dibuat dari kelas itu, tetapi saya tidak bisa melihat mengapa itu secara eksplisit perlu ditambahkan ke setiap fungsi sebagai parameter. Untuk mengilustrasikan, di Ruby saya bisa melakukan ini:

class myClass
    def myFunc(name)
        @name = name
    end
end

Yang saya pahami, cukup mudah. Namun dengan Python saya perlu memasukkan self:

class myClass:
    def myFunc(self, name):
        self.name = name

Adakah yang bisa berbicara dengan saya melalui ini? Ini bukan sesuatu yang saya temui dalam pengalaman saya (yang diakui terbatas).


883
2018-04-25 20:22


asal


Jawaban:


Alasan yang perlu Anda gunakan self. karena Python tidak menggunakan @ sintaks untuk merujuk ke atribut instan. Python memutuskan untuk melakukan metode dengan cara yang membuat contoh di mana metode itu berada lulus secara otomatis, tetapi tidak diterima secara otomatis: parameter pertama dari metode adalah contoh metode dipanggil. Itu membuat metode sepenuhnya sama dengan fungsi, dan membiarkan nama sebenarnya digunakan untuk Anda (meskipun self adalah konvensi, dan orang pada umumnya akan cemberut pada Anda ketika Anda menggunakan sesuatu yang lain.) self tidak khusus untuk kode, itu hanya objek lain.

Python dapat melakukan sesuatu yang lain untuk membedakan nama normal dari atribut - sintaks khusus seperti Ruby, atau membutuhkan deklarasi seperti C ++ dan Java, atau mungkin sesuatu yang lebih berbeda - tetapi tidak. Python semua untuk membuat hal-hal yang eksplisit, membuatnya jelas apa yang apa, dan meskipun itu tidak melakukannya sepenuhnya di mana-mana, ia melakukannya misalnya atribut. Itu sebabnya menugaskan ke atribut instance perlu tahu instance apa yang harus ditetapkan, dan itulah mengapa itu perlu self..


584
2018-04-25 20:25



Mari kita ambil kelas vektor sederhana:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

Kami ingin memiliki metode yang menghitung panjangnya. Apa yang akan terlihat jika kita ingin mendefinisikannya di dalam kelas?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

Apa yang seharusnya terlihat ketika kita mendefinisikannya sebagai metode / fungsi global?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

Jadi seluruh struktur tetap sama. Bagaimana saya bisa memanfaatkan ini? Jika kita berasumsi sejenak bahwa kita tidak menulis length metode untuk kami Vector kelas, kita bisa melakukan ini:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

Ini berfungsi karena parameter pertama length_global, dapat digunakan kembali sebagai self parameter dalam length_new. Ini tidak akan mungkin tanpa eksplisit self.


Cara lain untuk memahami kebutuhan akan eksplisit self adalah untuk melihat di mana Python menambahkan beberapa gula sintaksis. Ketika Anda ingat, pada dasarnya, panggilan seperti

v_instance.length()

secara internal diubah menjadi

Vector.length(v_instance)

mudah untuk melihat di mana self cocok. Anda tidak benar-benar menulis metode instan dengan Python; apa yang Anda tulis adalah metode kelas yang harus mengambil contoh sebagai parameter pertama. Karenanya, Anda harus menempatkan parameter instance di suatu tempat secara eksplisit.


382
2018-04-28 00:03



Katakanlah Anda memiliki kelas ClassA yang berisi metode methodA didefinisikan sebagai:

def methodA(self, arg1, arg2):
    # do something

dan ObjectA adalah contoh dari kelas ini.

Sekarang kapan ObjectA.methodA(arg1, arg2) disebut, python internal mengubahnya untuk Anda sebagai:

ClassA.methodA(ObjectA, arg1, arg2)

Itu self variabel mengacu pada objek itu sendiri.


283
2018-01-26 17:31



Ketika objek dipakai, objek itu sendiri dilewatkan ke parameter diri.

enter image description here

Karena ini, data objek terikat pada objek. Di bawah ini adalah contoh bagaimana Anda mungkin ingin memvisualisasikan apa yang mungkin terlihat oleh setiap data objek. Perhatikan bagaimana ‘diri’ diganti dengan nama objek. Saya tidak mengatakan contoh diagram di bawah ini benar-benar akurat tetapi mudah-mudahan dengan melayani tujuan dalam memvisualisasikan penggunaan diri.

enter image description here

Objek dilewatkan ke dalam parameter sendiri sehingga objek dapat menyimpan data sendiri.

Meskipun ini mungkin tidak sepenuhnya akurat, pikirkan proses instantiating objek seperti ini: Ketika suatu objek dibuat menggunakan kelas sebagai template untuk data dan metode sendiri. Tanpa melewatkan namanya sendiri ke dalam parameter diri, atribut dan metode di kelas akan tetap sebagai template umum dan tidak akan direferensikan ke (milik) objek. Jadi dengan meneruskan nama objek ke dalam parameter diri itu berarti bahwa jika 100 objek dipakai dari satu kelas, mereka semua dapat melacak data dan metode mereka sendiri.

Lihat ilustrasi di bawah ini:

enter image description here


151
2018-06-28 05:47



Saya suka contoh ini:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []

65
2018-04-26 16:02



Saya akan menunjukkan dengan kode itu tidak menggunakan kelas:

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

Kelas hanya merupakan cara untuk menghindari melewatkan hal "keadaan" ini sepanjang waktu (dan hal-hal baik lainnya seperti menginisialisasi, komposisi kelas, metaclasses yang jarang dibutuhkan, dan mendukung metode khusus untuk mengganti operator).

Sekarang mari kita mendemonstrasikan kode di atas menggunakan mesin kelas python built-in, untuk menunjukkan bagaimana pada dasarnya hal yang sama.

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[memigrasi jawaban saya dari pertanyaan tertutup duplikat]


33
2018-06-22 00:27



Serta semua alasan lain sudah dinyatakan, memungkinkan untuk akses lebih mudah untuk metode yang ditimpa; Anda bisa menelepon Class.some_method(inst).

Contoh di mana itu berguna:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"

17
2018-04-25 20:31



Kutipan berikut berasal dari Dokumentasi Python tentang diri:

Seperti pada Modula-3, tidak ada singkatan [dalam Python] untuk merujuk anggota objek dari metodenya: fungsi metode dideklarasikan dengan argumen pertama eksplisit yang mewakili objek, yang diberikan secara implisit oleh panggilan.

Seringkali, argumen pertama dari suatu metode disebut self. Ini tidak lebih dari sebuah konvensi: nama diri sama sekali tidak memiliki arti khusus untuk Python. Perhatikan, bagaimanapun, bahwa dengan tidak mengikuti konvensi, kode Anda mungkin kurang dapat dibaca oleh pemrogram Python lainnya, dan juga dapat dibayangkan bahwa program browser kelas mungkin ditulis yang bergantung pada konvensi semacam itu.

Untuk informasi lebih lanjut, lihat Tutorial dokumentasi Python di kelas.


16
2018-04-25 20:29