程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Python >> Python面向對象編程

Python面向對象編程

編輯:Python
一、什麼是面向對象

  面向對象編程(OOP,Object Oriented Programming)
  OOP三個主要的特征:數據封裝、繼承和多態。
  所有的程序是由一定的屬性和行為對象組成的,不同的對象的訪問通過函數調用來完成,對象間所有的交流都是通過方法調用,通過對封裝對象數據,提高復用率。

二、創建類和對象

  面向對象編程是一種編程方式,此編程方式的落地需要使用 "類" 和 "對象"來實現,所以,面向對象編程其實就是對 "類" 和 "對象" 的使用。

  類就是一個模板,模板裡可包含多個函數,函數裡實現一些功能。對象則是根據模板創建的實例,通過實例對象可以執行類中的方法。

class Role (object):
    def __init__(self,name):
    self.name = name
  
    def buy_weapon(self,weapon):
    pass
  class是關鍵字,定義一個類,其名稱為Role,這個類繼承了Python的父類,名為object。在類的下面可以看到有很多函數的定義,但在 class中,函數被稱為方法,所以這裡暫時在一個名為Role類的下面有__init__和buy_weapon方法。
三、封裝

  封裝,顧名思義就是將內容封裝到某個地方,以後再去調用被封裝在某處的內容。

  所以,在使用面向對象的封裝特性時,需要:1.將內容封裝到某處 2.從某處調用被封裝的內容

class Role (object):    #object是父類,繼承父類
    def __init__(self,name,role,weapon,life_value):     #稱為構造方法,根據類創建對象時自動執行
        self.name = name    #成員變量,self 代表傳進來的name,在整個類都可以使用這個變量,把一個局部變量變為了全局變量
        self.role = role
        self.weapon = weapon
        self.life_val = life_value
   
    def buy_weapon(self,weapon):
        print("[%s] is buying [%s]" % (self.name,weapon))
        self.weapon = weapon
   
# 把一個抽象的類變成一個具體的過程叫實例化
t1 = Role("Stanley",'Terrorist','Glock',100)    #等價於Role(t1,"Stanley",'Terrorist','b11',100),同時將'Stanley'、'Terrorist'、'Glock'和100封裝到t1和self的name、role、weapon、life_value屬性中
p1 = Role("Tom",'Police','Desert Eagle',90) #Role(p1,"Tom",'Police','Desert Eagle',90)
print("t1's weapon was [%s] before" % t1.weapon)
print("=".center(40,'='))
t1.buy_weapon('AK47')    #轉換為Role.buy_weapon(t1,'AK47')
print("t1's weapon is [%s] now" % t1.weapon)
  
Result:
t1's weapon was [Glock] before
========================================
[Stanley] is buying [AK47]
t1's weapon is [AK47] now

  第一個方法__init__是初始化構造方法,構造方法的第一個參數永遠是self,表示這個類的對象本身,真正構造對象時,self這個參數不用寫,python編譯器會自己加上去,構造方法的作用就是對self對象進行賦值,如下面傳進來的name賦給self.name,這麼做的目的是因為在class中,每個方法依舊是要遵循函數規則的,在函數下面每個變量都是局部變量,在其他函數中並不能相互調用,如此做就把一個局部變量變為全局變量。

  通過self間接調用被封裝的內容:

  第二個方法除了編譯器會自己加上去的self參數外,weapon參數接收傳入的變量,打印調用的參數。在print之後self.name含義是將調用者的name賦值給self。

  接下來要對p1和t1進行實例化,這是將一個抽象的類變成一個具體的過程,生成了p1和t1兩個角色。t1 = Role("Stanley",'Terrorist','Glock',100),Python解釋器會將此轉換為 Role(t1,"Stanley",'Terrorist','Glock',100),這裡通過解釋器轉換後的t1其實就是self。

  現在t1角色進行購買行為,t1.buy_weapon('AK47'),Python解釋器會將此轉換為 Role.buy_weapon(t1,'AK47'),如上所述此時的t1就是self,也可理解為將t1傳入__init__初始化構造方法,就可直接self.name(等價於t1.name)獲取到name的變量了(Stanley)。

  綜上所述,對於面向對象的封裝來說,其實就是使用構造方法將內容封裝到對象中,然後通過對象直接或者self間接獲取被封裝的內容。

四、繼承

  繼承,面向對象中的繼承和現實生活中的繼承相同,即:子可以繼承父的內容,也可理解為由一般到特殊。

class SchoolMember(object):
    member_nums = 0
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
        self.enroll()
 
    def enroll(self):
        print("NO.%s SchoolMember [%s] is enrolled!" % (SchoolMember.member_nums,self.name))
        SchoolMember.member_nums += 1   #統計人員數量不可寫為self.member_nums += 1,因self實例下沒有此變量,兩者毫無關聯。
 
    def tell(self):
        print("Hello, My name is [%s]" % self.name)
 
class Teacher(SchoolMember):    #參數為繼承對象
    def __init__(self,name,age,sex,course,salary):  #如果不寫__init__默認就繼承了父類的所有屬性,但子類需要額外擴展,需先重寫再繼承
        super(Teacher,self).__init__(name,age,sex)      #上面進行了重寫,再繼承回來進行覆蓋,推薦新式類語法
        #SchoolMember.__init__(self,name,age,sex)        #此為經典類語法,不推薦
        self.course = course
        self.salary = salary
 
    def teaching(self):
        print("Teacher [%s] is teaching [%s]" % (self.name,self.course))
 
class Student(SchoolMember):
    def __init__(self,name,age,sex,course,tuition,):
        super(Student,self).__init__(name,age,sex)
        self.course = course
        self.tuition = tuition
 
    def pay_tuition(self):
        print("Student [%s] pays tuition [%s] again" % (self.name,self.tuition))
 
#實例化老師
t1 = Teacher('Stanley',24,'M','Python',1000)    #實例化,不可實例化SchoolMember,其只可用來繼承
t1 = Teacher('Katrina',29,'M','MySQL',1500)    #實例化,不可實例化SchoolMember,其只可用來繼承
#實例化學生
s1 = Student('Tim',24,'F','MySQL',10000)
s2 = Student('Bella',27,'M','Python',12000)
print("===========子類使用父類方法============")
t1.tell()
s1.tell()
print("===========子類使用私有方法============")
t1.teaching()
s1.pay_tuition()
 
Result:
NO.0 SchoolMember [Stanley] is enrolled!
NO.1 SchoolMember [Katrina] is enrolled!
NO.2 SchoolMember [Tim] is enrolled!
NO.3 SchoolMember [Bella] is enrolled!
===========子類使用父類方法============
Hello, My name is [Katrina]
Hello, My name is [Tim]
===========子類使用私有方法============
Teacher [Katrina] is teaching [MySQL]
Student [Tim] pays tuition [10000] again

  此為標准繼承示例,其中包含三個類,SchoolMember是父類,Teacher和Student是子類,子類中擁有父類的共同屬性,除此之外,子類還需要額外進行擴展,所以在子類中要先重寫,再從父類繼承回來進行覆蓋。在繼承語法中super為關鍵字,不可省略,其參數為子類名稱,self,__init__參數為需要繼承的屬性。相關封裝特性詳見上一段落,不再累述。父類和子類定義好後,實例化Teacher和 Student,在父類中執行注冊方法,每個子類都可調用父類的tell方法,並且每個子類都會包含私有方法teaching和pay_tuition,這就利用繼承特性實現了簡單的權限限制功能。

  綜上所述,對於面向對象的繼承來說,其實就是將多個類共有的方法提取到父類中,子類僅需繼承父類而不必一一實現每個方法。

五、多態

    多態性(polymorphisn)是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。

    Pyhon不支持多態並且也用不到多態,多態的概念是應用於Java和C#這一類強類型語言中的。那麼,多態的作用是什麼呢?我們知道,封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了——代碼重用。而多態則是為了實現另一個目的——接口重用!多態的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確調用。

通過Python模擬的多態:

class Animal:
    def __init__(self, name):    # Constructor of the class
        self.name = name
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")
 
class Cat(Animal):
    def talk(self):
        return 'Meow!'
 
class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'
 
animals = [Cat('Missy'),
           Dog('Lassie')]
 
for animal in animals:
    print animal.name + ': ' + animal.talk()
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved