Sebelum memperkenalkan penggunaan diri dalam Python, mari kita perkenalkan dahulu kelas dan kejadian dalam Python
Kami tahu bahawa konsep berorientasikan objek yang paling penting ialah kelas dan contoh adalah templat abstrak perkara seperti pelajar boleh diwakili oleh kelas Pelajar. Instance ialah "objek" khusus yang dibuat berdasarkan kelas Setiap objek mewarisi kaedah yang sama daripada kelas, tetapi datanya mungkin berbeza.
1. Ambil kelas Pelajar sebagai contoh Dalam Python, kelas ditakrifkan seperti berikut:
class Student(object): pass
(Objek) menunjukkan kelas mana yang diwarisi oleh kelas Objek akan mewarisi.
2 Contoh: Selepas kelas ditakrifkan, anda boleh mencipta tika Pelajar melalui kelas Pelajar Mencipta tika dicapai melalui nama kelas + ():
student = Student()
3. Oleh kerana kelas memainkan peranan templat adalah untuk mengisi secara paksa atribut yang kami fikir mesti terikat semasa membuat contoh. Di sini kita menggunakan kaedah __init__
, kaedah terbina dalam Python Contohnya, dalam kelas Pelajar, ikat atribut seperti nama dan skor kepadanya:
class Student(object): def __init__(self, name, score): self.name = name self.score = score
Nota di sini: (1), yang. bahagian pertama kaedah __init__
Parameter pertama sentiasa self
, yang mewakili kelas yang dicipta sendiri Oleh itu, di dalam kaedah __init__
, anda boleh mengikat pelbagai atribut kepada diri sendiri, kerana diri menunjuk kepada contoh yang dibuat itu sendiri. (2) Dengan kaedah __init__
, apabila membuat contoh, anda tidak boleh menghantar parameter kosong Anda mesti memasukkan parameter yang sepadan dengan kaedah __init__
, tetapi diri tidak perlu dihantar Jurubahasa Python akan pembolehubah Instance diluluskan dalam:
>>>student = Student("Hugh", 99) >>>student.name "Hugh" >>>student.score 99
Selain itu, di sini self
merujuk kepada kelas itu sendiri dan self.name
ialah pembolehubah atribut kelas Student
, yang dimiliki oleh kelas Student
. Dan name
ialah parameter luaran, bukan parameter yang disertakan dengan kelas Student
. Oleh itu, self.name = name
bermaksud untuk memberikan nilai parameter luaran name
kepada pembolehubah atribut kelas Pelajar sendiri self.name
.
4 Berbanding dengan nombor biasa, hanya terdapat satu perbezaan apabila mentakrifkan fungsi dalam kelas, iaitu parameter pertama sentiasa pembolehubah contoh kelas itu sendiri. self
Dan apabila membuat panggilan, tidak perlu melepasi parameter ini. Selain itu, kaedah kelas (fungsi) tidak berbeza daripada fungsi biasa Anda boleh menggunakan parameter lalai, parameter pembolehubah atau parameter kata kunci (*args ialah parameter berubah, args Apa yang diterima ialah tuple<. 🎜>, **kw ialah parameter kata kunci dan kw menerima dict).
Pelajar sendiri memiliki data ini, maka untuk mengakses data ini, tidak perlu mengaksesnya daripada fungsi luaran, tetapi boleh ditakrifkan secara langsung dalam kelas Pelajar. . Fungsi (kaedah) data, supaya "data" boleh dikapsulkan. Fungsi yang merangkum data ini dikaitkan dengan kelas Pelajar itu sendiri, dan dipanggil kaedah kelas:
class Student(obiect): def __init__(self, name, score): self.name = name self.score = score def print_score(self): print "%s: %s" % (self.name, self.score)
>>>student = Student("Hugh", 99) >>>student.print_score Hugh: 99
Data dan logik ini dirangkumkan, menjadikannya mudah untuk dipanggil, tetapi anda tidak mengetahui butiran pelaksanaan dalaman.
Jika anda ingin menghalang atribut dalaman daripada diakses secara luaran, anda boleh menambah dua garis bawahsebelum nama atribut Dalam Python, jika nama pembolehubah bagi suatu contoh bermula dengan , kemudian Ia menjadi pembolehubah persendirian (peribadi), yang hanya boleh diakses secara dalaman dan bukan secara luaran Oleh itu, kami menukar kelas Pelajar:
class Student(object): def __init__(self, name, score): self.__name = name self.__score = score def print_score(self): print "%s: %s" %(self.__name,self.__score)
dan pembolehubah instance .__name
tidak lagi boleh diakses dari luar: .__score
>>> student = Student('Hugh', 99) >>> student.__name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute '__name'
class Student(object): ... def get_name(self): return self.__name def get_score(self): return self.__score
class Student(object): ... def set_score(self, score): self.__score = score
, iaitu nama yang bermula dengan garis bawah berganda dan berakhir dengan dua kali ganda. garis bawah ialah pembolehubah khas. __xxx__
__name__
Kadangkala, anda akan melihat nama pembolehubah contoh bermula dengan garis bawah, seperti _name Pembolehubah contoh sedemikian boleh diakses secara luaran, bagaimanapun, mengikut konvensyen, apabila anda melihat pembolehubah tersebut Apabila, ia bermakna, ". Walaupun saya boleh diakses, sila anggap saya sebagai pembolehubah peribadi dan jangan mengaksesnya sesuka hati." Satu lagi faedah pengkapsulan __score__
ialah anda boleh menambah kaedah baharu
ke kelas Pelajar pada bila-bila masa, seperti::class Student(object):
...
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
get_grade
kaedah boleh terus Dipanggil pada pembolehubah contoh, tidak perlu mengetahui butiran pelaksanaan dalaman:
>>> student.get_grade() 'A'
6、self
的仔细用法
(1)、self代表类的实例,而非类。
class Test: def ppr(self): print(self) print(self.__class__) t = Test() t.ppr() 执行结果: <__main__.Test object at 0x000000000284E080> <class '__main__.Test'>
从上面的例子中可以很明显的看出,self代表的是类的实例。而self.__class__
则指向类。
注意:把self换成this,结果也一样,但Python中最好用约定俗成的self。
(2)、self可以不写吗?
在Python解释器的内部,当我们调用t.ppr()时,实际上Python解释成Test.ppr(t),也就是把self替换成了类的实例。
class Test: def ppr(): print(self) t = Test() t.ppr()
运行结果如下:
Traceback (most recent call last):
File "cl.py", line 6, in
t.ppr()
TypeError: ppr() takes 0 positional arguments but 1 was given
运行时提醒错误如下:ppr在定义时没有参数,但是我们运行时强行传了一个参数。
由于上面解释过了t.ppr()等同于Test.ppr(t),所以程序提醒我们多传了一个参数t。
这里实际上已经部分说明了self
在定义时不可以省略。
当然,如果我们的定义和调用时均不传类实例是可以的,这就是类方法。
class Test: def ppr(): print(__class__) Test.ppr() 运行结果: <class '__main__.Test'>
(3)、在继承时,传入的是哪个实例,就是那个传入的实例,而不是指定义了self的类的实例。
class Parent: def pprt(self): print(self) class Child(Parent): def cprt(self): print(self) c = Child() c.cprt() c.pprt() p = Parent() p.pprt()
运行结果:
<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>
解释:
运行c.cprt()时应该没有理解问题,指的是Child类的实例。
但是在运行c.pprt()时,等同于Child.pprt(c),所以self指的依然是Child类的实例,由于self中没有定义pprt()方法,所以沿着继承树往上找,发现在父类Parent中定义了pprt()方法,所以就会成功调用。
(4)、在描述符类中,self指的是描述符类的实例
class Desc: def __get__(self, ins, cls): print('self in Desc: %s ' % self ) print(self, ins, cls) class Test: x = Desc() def prt(self): print('self in Test: %s' % self) t = Test() t.prt() t.x
运行结果如下:
self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8>
这里主要的疑问应该在:Desc类中定义的self不是应该是调用它的实例t吗?怎么变成了Desc类的实例了呢?
因为这里调用的是t.x,也就是说是Test类的实例t的属性x,由于实例t中并没有定义属性x,所以找到了类属性x,而该属性是描述符属性,为Desc类的实例而已,所以此处并没有顶用Test的任何方法。
那么我们如果直接通过类来调用属性x也可以得到相同的结果。
下面是把t.x改为Test.x运行的结果。
self in Test: <__main__.Test object at 0x00000000022570B8> self in Desc: <__main__.Desc object at 0x000000000223E208> <__main__.Desc object at 0x000000000223E208> None <class '__main__.Test'>
Atas ialah kandungan terperinci Bagaimana untuk menggunakan diri dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!