Python berorientasikan objek


Python telah menjadi bahasa berorientasikan objek dari awal kerana ini, adalah mudah untuk mencipta kelas dan objek dalam Python. Dalam bab ini kami akan memperkenalkan pengaturcaraan berorientasikan objek dalam Python secara terperinci.

Jika anda belum pernah didedahkan kepada bahasa pengaturcaraan berorientasikan objek sebelum ini, anda mungkin perlu terlebih dahulu memahami beberapa ciri asas bahasa berorientasikan objek dan membentuk konsep asas berorientasikan objek dalam fikiran anda, yang akan membantu anda Mempelajari pengaturcaraan berorientasikan objek dengan mudah dalam Python.

Seterusnya, mari kita fahami secara ringkas beberapa ciri asas berorientasikan objek.


Pengenalan kepada teknologi berorientasikan objek

  • Kelas (Kelas): digunakan untuk menerangkan koleksi objek dengan sifat dan kaedah yang sama. Ia mentakrifkan sifat dan kaedah yang biasa kepada setiap objek dalam koleksi. Objek ialah contoh kelas.

  • Pembolehubah kelas: Pembolehubah kelas adalah perkara biasa di seluruh objek yang di instantiated. Pembolehubah kelas ditakrifkan di dalam kelas dan di luar badan fungsi. Pembolehubah kelas biasanya tidak digunakan sebagai pembolehubah contoh.

  • Ahli data: Pembolehubah kelas atau pembolehubah ins digunakan untuk memproses data yang berkaitan dengan kelas dan objek instancenya.

  • Penulisan semula kaedah: Jika kaedah yang diwarisi daripada kelas induk tidak dapat memenuhi keperluan subkelas, ia boleh ditulis semula. , juga dikenali sebagai kaedah mengatasi.

  • Pembolehubah tika: Pembolehubah yang ditakrifkan dalam kaedah hanya bertindak pada kelas tika semasa.

  • Warisan: Iaitu, kelas terbitan mewarisi medan dan kaedah kelas asas. Warisan juga membenarkan objek kelas terbitan untuk dianggap sebagai objek kelas asas. Sebagai contoh, terdapat reka bentuk sedemikian: objek jenis Anjing berasal daripada kelas Haiwan, yang menyerupai perhubungan "ialah-a" (contohnya, Anjing ialah Haiwan).

  • Instansiasi: Cipta tika kelas, objek khusus kelas.

  • Kaedah: Fungsi yang ditakrifkan dalam kelas.

  • Objek: Contoh struktur data yang ditakrifkan oleh kelas. Objek termasuk dua ahli data (pembolehubah kelas dan pembolehubah contoh) dan kaedah.


Buat kelas

Gunakan penyataan kelas untuk mencipta kelas baharu, diikuti dengan kelas ialah nama kelas dan berakhir dengan titik bertindih, sebagai dalam contoh berikut:

class ClassName:
   '类的帮助信息'   #类文档字符串
   class_suite  #类体

Maklumat bantuan kelas boleh dilihat melalui ClassName.__doc__.

class_suite terdiri daripada ahli kelas, kaedah dan atribut data.

Instance

Berikut ialah contoh kelas Python yang mudah:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Employee:
   '所有员工的基类'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary
  • pembolehubah empCount ialah pembolehubah kelas, nilainya akan berada dalam kelas ini Shared antara semua kejadian. Anda boleh mengaksesnya menggunakan Employee.empCount dalam kelas dalam atau kelas luar.

  • Kaedah pertama __init__() ialah kaedah khas, dipanggil pembina atau kaedah permulaan kelas, yang dipanggil apabila contoh kelas ini dicipta Kaedah


Buat objek contoh

Untuk mencipta tika kelas, anda menggunakan nama kelas dan menerima argumen melalui kaedah __init__.

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)

Mengakses Sifat

Anda boleh menggunakan titik (.) untuk mengakses sifat objek. Gunakan nama kelas berikut untuk mengakses pembolehubah kelas:

emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

Contoh penuh:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Employee:
   '所有员工的基类'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

Laksanakan kod di atas dan hasil output adalah seperti berikut:

Name :  Zara ,Salary:  2000
Name :  Manni ,Salary:  5000
Total Employee 2

Anda boleh menambah, padam, dan ubah suai atribut kelas , seperti yang ditunjukkan di bawah:

emp1.age = 7  # 添加一个 'age' 属性
emp1.age = 8  # 修改 'age' 属性
del emp1.age  # 删除 'age' 属性

Anda juga boleh menggunakan fungsi berikut untuk mengakses atribut:

  • getattr(obj, name[ , lalai]): akses harta objek.

  • hasattr(obj,name) : Semak sama ada atribut wujud.

  • setattr(obj,nama,nilai): Tetapkan atribut. Jika harta itu tidak wujud, harta baru dicipta.

  • delattr(obj, nama): Padamkan atribut.

hasattr(emp1, 'age')    # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age')    # 返回 'age' 属性的值
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
delattr(empl, 'age')    # 删除属性 'age'

Atribut kelas terbina dalam Python

  • __dict__: atribut kelas (mengandungi kamus yang terdiri daripada atribut data kelas)

  • __doc__: Rentetan dokumentasi kelas

  • __name__: Nama kelas

  • __modul__: Definisi kelas Modul di mana ia terletak (nama penuh kelas ialah '__main__.className', jika kelas terletak dalam modul mymod yang diimport, maka className.__module__ adalah sama dengan mymod)

  • __bases__: semua kelas induk kelas Elemen konstituen (mengandungi tuple yang terdiri daripada semua kelas induk)

Contoh memanggil atribut kelas terbina dalam Python adalah sebagai berikut:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Employee:
   '所有员工的基类'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

print "Employee.__doc__:", Employee.__doc__
print "Employee.__name__:", Employee.__name__
print "Employee.__module__:", Employee.__module__
print "Employee.__bases__:", Employee.__bases__
print "Employee.__dict__:", Employee.__dict__

Hasil keluaran melaksanakan kod di atas adalah seperti berikut:

Employee.__doc__: 所有员工的基类
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}

pemusnahan objek python (pengumpulan sampah)

Seperti bahasa Java, Python menggunakan teknologi mudah yang dipanggil pengiraan rujukan untuk mengesan objek dalam ingatan.

Secara dalaman, Python merekodkan bilangan rujukan yang dimiliki oleh setiap objek yang digunakan.


Pembolehubah penjejakan dalaman, dipanggil kaunter rujukan.

Apabila objek dicipta, kiraan rujukan dibuat Apabila objek tidak diperlukan lagi. Iaitu, apabila kiraan rujukan objek ini menjadi 0, ia adalah sampah yang dikumpul. Tetapi kitar semula bukanlah "segera"; Jurubahasa akan mengitar semula ruang memori yang diduduki oleh objek sampah pada masa yang sesuai.

a = 40      # 创建对象  <40>
b = a       # 增加引用, <40> 的计数
c = [b]     # 增加引用.  <40> 的计数

del a       # 减少引用 <40> 的计数
b = 100     # 减少引用 <40> 的计数
c[0] = -1   # 减少引用 <40> 的计数

Mekanisme kutipan sampah bukan sahaja menyasarkan objek dengan kiraan rujukan 0, tetapi juga boleh mengendalikan rujukan bulat. Rujukan bulat berlaku apabila dua objek merujuk antara satu sama lain, tetapi tiada pembolehubah lain merujuk kepada mereka. Dalam kes ini, pengiraan rujukan sahaja tidak mencukupi. Pengumpul sampah Python sebenarnya adalah kaunter rujukan dan pengumpul sampah kitaran. Selain pengiraan rujukan, pemungut sampah juga melihat objek yang telah diperuntukkan dalam jumlah yang besar (dan yang belum dimusnahkan oleh pengiraan rujukan). Dalam kes ini, jurubahasa akan berhenti seketika dan cuba membersihkan sebarang gelung yang tidak dirujuk.

Instance

Destructor __del__, __del__ dipanggil apabila objek dimusnahkan Apabila objek tidak lagi digunakan, kaedah __del__ berjalan:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Point:
   def __init__( self, x=0, y=0):
      self.x = x
      self.y = y
   def __del__(self):
      class_name = self.__class__.__name__
      print class_name, "销毁"

pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # 打印对象的id
del pt1
del pt2
del pt3

di atas Hasil daripada berjalan. contohnya adalah seperti berikut:

3083401324 3083401324 3083401324
Point 销毁

Nota: Biasanya anda perlu mentakrifkan kelas dalam fail berasingan,

Warisan kelas

Objek- berorientasikan Salah satu faedah utama yang dibawa oleh pengaturcaraan ialah penggunaan semula kod, dan salah satu cara untuk mencapai penggunaan semula ini adalah melalui mekanisme pewarisan. Warisan boleh difahami sepenuhnya sebagai hubungan jenis dan subjenis antara kelas.

Perkara yang perlu diberi perhatian: Sintaks warisan nama kelas Terbitan kelas (Nama kelas asas): //... Nama kelas asas ditulis dalam kurungan, dan kelas asas ialah Ia dinyatakan dalam tuple apabila kelas ditakrifkan.

Sesetengah ciri warisan dalam ular sawa:

  • 1: Dalam warisan, pembinaan kelas asas (__init__() kaedah) tidak akan dipanggil secara automatik, ia perlu Panggilnya secara khusus dalam pembina kelas terbitannya.

  • 2: Apabila memanggil kaedah kelas asas, anda perlu menambah awalan nama kelas kelas asas, dan anda perlu membawa pembolehubah parameter diri. Berbeza daripada memanggil fungsi biasa dalam kelas, anda tidak perlu membawa parameter diri

  • 3: Python sentiasa terlebih dahulu mencari kaedah jenis yang sepadan, jika ia tidak dapat mencari yang sepadan kaedah dalam kaedah kelas terbitan, ia mula mencari satu demi satu dalam kelas asas. (Mula-mula cari kaedah panggilan dalam kelas ini, dan kemudian cari dalam kelas asas jika anda tidak menemuinya).

Jika lebih daripada satu kelas disenaraikan dalam tuple warisan, maka ia dipanggil "warisan berbilang".

Sintaks:

Pengisytiharan kelas terbitan, serupa dengan kelas induknya, dengan senarai kelas asas yang diwarisi mengikut nama kelas, seperti berikut:

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

Instance:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Parent:        # 定义父类
   parentAttr = 100
   def __init__(self):
      print "调用父类构造函数"

   def parentMethod(self):
      print '调用父类方法'

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print "父类属性 :", Parent.parentAttr

class Child(Parent): # 定义子类
   def __init__(self):
      print "调用子类构造方法"

   def childMethod(self):
      print '调用子类方法 child method'

c = Child()          # 实例化子类
c.childMethod()      # 调用子类的方法
c.parentMethod()     # 调用父类方法
c.setAttr(200)       # 再次调用父类的方法
c.getAttr()          # 再次调用父类的方法

Hasil pelaksanaan kod di atas adalah seperti berikut:

调用子类构造方法
调用子类方法 child method
调用父类方法
父类属性 : 200

Anda boleh mewarisi berbilang kelas

class A:        # 定义类 A
.....

class B:         # 定义类 B
.....

class C(A, B):   # 继承类 A 和 B
.....

Anda boleh menggunakan issubclass() atau isinstance( ) kaedah untuk menguji.

  • issubclass() - Fungsi Boolean untuk menentukan sama ada kelas ialah subkelas atau turunan kelas lain, sintaks: issubclass(sub,sup)

  • isinstance(obj, Class) Fungsi Boolean mengembalikan benar jika obj ialah objek instance bagi kelas Class atau objek instance subclass Class.


Penulisan semula kaedah

Jika fungsi kaedah kelas induk anda tidak dapat memenuhi keperluan anda, anda boleh mengatasi kaedah kelas induk anda dalam subkelas :

Contoh:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Parent:        # 定义父类
   def myMethod(self):
      print '调用父类方法'

class Child(Parent): # 定义子类
   def myMethod(self):
      print '调用子类方法'

c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法

Hasil output untuk melaksanakan kod di atas adalah seperti berikut:

调用子类方法

Kaedah beban asas asas

Jadual berikut menyenaraikan beberapa biasa Anda boleh mengatasi fungsi dalam kelas anda sendiri:

< td>3
Nombor siri Kaedah, penerangan & panggilan mudah
1
序号方法, 描述 & 简单的调用
1__init__ ( self [,args...] )
构造函数
简单的调用方法: obj = className(args)
2__del__( self )
析构方法, 删除一个对象
简单的调用方法 : dell obj
3__repr__( self )
转化为供解释器读取的形式
简单的调用方法 : repr(obj)
4__str__( self )
用于将值转化为适于人阅读的形式
简单的调用方法 : str(obj)
5__cmp__ ( self, x )
对象比较
简单的调用方法 : cmp(obj, x)
__init__ ( self [,args...] )<🎜>< br />Pembina
Kaedah panggilan mudah: obj = className(args)
2< 🎜>__del__ ( self )<🎜>
Kaedah pemusnah, padam objek
Kaedah panggilan mudah: dell obj
<🎜>__repr__( self )<🎜>
Tukar kepada borang yang dibaca oleh jurubahasa
Kaedah panggilan mudah: repr(obj)< /em>
4<🎜>__str__( self )<🎜>
Digunakan untuk menukar nilai kepada Borang yang boleh dibaca manusia
Kaedah panggilan mudah : str(obj)
5<🎜>__cmp__ ( diri, x )<🎜>
Perbandingan objek
Kaedah panggilan mudah: cmp(obj, x)

Operator overloading

Python juga menyokong operator overloading, contohnya adalah seperti berikut:

#!/usr/bin/python

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2

Hasil pelaksanaan kod di atas adalah seperti berikut:

Vector(7,8)

Atribut kelas Atribut peribadi kelas

__private_attrs

dengan kaedah : bermula dengan dua garis bawah, mengisytiharkan bahawa atribut itu peribadi dan tidak boleh digunakan atau secara langsung diakses di luar kelas. Apabila digunakan dalam kaedah di dalam kelas self.__private_attrs.

Kaedah kelas

Dalam kelas, anda boleh menggunakan kata kunci def untuk mentakrifkan kaedah untuk kelas Berbeza daripada definisi fungsi umum, kaedah kelas mesti mengandungi parameter diri, iaitu parameter pertama.

Kaedah peribadi kelas

__kaedah_pribadi: Bermula dengan dua garis bawah, kaedah diisytiharkan sebagai kaedah persendirian dan tidak boleh dipanggil di luar kelas. Memanggil self.__private_methods

instance

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class JustCounter:
	__secretCount = 0  # 私有变量
	publicCount = 0    # 公开变量

	def count(self):
		self.__secretCount += 1
		self.publicCount += 1
		print self.__secretCount

counter = JustCounter()
counter.count()
counter.count()
print counter.publicCount
print counter.__secretCount  # 报错,实例不能访问私有变量

Python di dalam kelas dengan menukar nama untuk memasukkan nama kelas:

1
2
2
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    print counter.__secretCount  # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'

Python tidak membenarkan instantiation Kelas mengakses data peribadi, tetapi anda boleh menggunakan object._className__attrName untuk mengakses atribut Gantikan baris terakhir kod di atas dengan kod berikut:

.........................
print counter._JustCounter__secretCount

Laksanakan kod di atas dan pelaksanaan. keputusan adalah seperti berikut:

1
2
2
2