1. 程式人生 > >Linux---python中的封裝(內建方法,初始化方法),繼承

Linux---python中的封裝(內建方法,初始化方法),繼承

面向物件中:哪一個物件呼叫的方法,self就是哪一個物件的引用

在類封裝的方法內部,self就表示當前呼叫方法的物件自己 呼叫方法時,程式設計師不需要傳遞self引數(但是定義的時候,第一個引數必須是self) 在方法內部:可以通過self.訪問物件的屬性 在方法內部:可以通過self.呼叫其他的物件方法 class Cat:     def eat(self):         print '%s愛吃魚' %self.name     def drink(self):         print '小貓要喝水' # 建立貓物件 tom = Cat() # 可以使用 .屬性名 利用賦值語句就可以了 tom.name = 'Tom'

tom.eat() tom.drink()

###內建方法### __del__方法:物件被從記憶體中銷燬前,會自動呼叫 __str__方法:返回物件的描述資訊 print 物件

__del__方法:

在python中     當一個物件被從記憶體中銷燬前(把這個物件從記憶體中刪除掉),會自動呼叫__del__方法 應用場景 __del__如果希望在物件被銷燬前,再做一些事情,可以考慮一下__del__方法

__str__方法: 在python中,使用python輸出物件變數,預設情況下,會輸出這個變數引用的物件是由哪>一個類建立的物件,以及在記憶體中的地址(十六進位制表示) 如果在開發中,希望使用print輸出物件變數時,能夠列印自定義的內容,就可以利用__str__這個內建方法了 class Cat:     def __init__(self,new_name):   ##__init__ 是python物件的內建方法         self.name = new_name         print '%s 來了' %self.name     def __del__(self):         print '%s 走了' %self.name     def __str__(self):   ##返回物件的描述資訊 print 物件         # 必須返回一個字串         return '我是 %s' %self.name

# tom是一個全域性變數 # 所以當我們的程式碼全部執行完之後,系統才會把tom這個物件進行回收 tom = Cat('Tom') print tom # print tom.name

# # del關鍵字,可以從記憶體中刪除一個物件,del關鍵字自己呼叫了__del__方法 # del tom # print '*' * 50

""" 生命週期 一個物件從呼叫類名()建立,宣告週期開始 一個物件的__del__方法一旦被呼叫,生命週期就結束 在物件的生命週期內,可以訪問物件的屬性,呼叫物件的方法 """

###初始化方法### 初始化方法:__init__ 是python物件的內建方法 __init__方法是專門用來定義一個類具有哪些屬性和方法的

初始化方法 我們現在已經知道了使用 類名() 就可以建立一個物件 當使用類名()建立物件時,python的直譯器會自動執行以下操作:     1.為物件在記憶體中分配空間--建立物件     2.呼叫初始化方法為物件的屬性設定初始值--初始化方法(__init__) 這個初始化方法就是__init__方法,__init__是物件的內建方法 __init__方法是專門用來定義一個類具有哪些屬性的方法

class Cat:     def __init__(self,new_name): # 與函式一樣         print '這是一個初始化方法'         # self.屬性名= 屬性的初始值         #self.name = 'Tom'         self.name = new_name     # 在類中 任何方法都可以使用這個self.name     def eat(self):         print '%s 愛吃魚' %self.name # 並沒有呼叫__init__方法 # 使用類名()建立物件的時候,會自動呼叫初始化方法__init__ tom = Cat('Tom') # 在__init__方法的內部使用 self.屬性名= 屬性的初始值 定義物件的屬性 # 定義屬性之後,再使用Cat類建立物件,都會擁有該屬性 print tom.name tom.eat()

lazy_cat=Cat('Lazy_cat') lazy_cat.eat()

###私有屬性和私有方法### 私有屬性和私有方法 應用場景及定義方式 應用場景     在實際開發中,物件的某些屬性或方法可能只希望在物件的內部使用,而不希望在外部被訪問到     私有屬性 就是 物件 不希望公開的 屬性     私有方法 就是 方法 不希望公開的 方法 定義方法     在定義屬性或方法時,在屬性名或者方法名前增加兩個下劃線,定義的就是私有屬性或方法 class Women:     def __init__(self,name):         self.name = name         self.__age = 18     def __secret(self):         print '%s 的年齡是 %d' %(self.name,self.__age)

lily = Women('lily') print lily.name # 私有屬性,外界不能直接訪問 #print lily.age # 私有方法,外界不能直接呼叫 lily.secret()

####面向物件中的三種形式:      封裝 繼承 多型####

   1.封裝:根據職責將屬性和方法封裝到一個抽象的類中    2.繼承:實現程式碼的重用,相同的程式碼不需要重複的寫    3.多型

###########################################

封裝 1.封裝是面向物件程式設計的一大特點 2.面向物件程式設計的第一步 將屬性和方法封裝到一個抽象的類中(為什麼說是抽象的,因為類不能直接使用) 3.外界使用類建立物件,然後讓物件呼叫方法 4.物件方法的細節都被封裝在類的內部

案例1:小明愛跑步 需求 1.小明體重75.0公斤 2.每次跑步會減肥0.5公斤 3每次吃東西體重會增加1公斤 4.小美的體重是45.0公斤 class Person:     def __init__(self,name,weight):         # 初始化方法中增加兩個引數由外界傳遞         # self.屬性 = 形參         self.name = name         self.weight = weight     def __str__(self):         return '我的名字叫 %s 體重是 %.2f' %(self.name,self.weight)     def run(self):         print '%s 愛跑步' %self.name         # 在物件方法的內部,是可以直接訪問物件的屬性         self.weight -= 0.5     def eat(self):         print '%s 吃東西' %self.name         self.weight += 1

xx = Person('小明',75.0) xx.run() xx.eat() print xx

# 同一個類創建出來的多個物件之間,屬性互補干擾 xm = Person('小美',45.0) xm.run() xm.eat() print xm print xx

案例2:擺放傢俱 需求: 1.房子有戶型,總面積和傢俱名稱列表     新房子沒有任何的傢俱 2.傢俱有名字和佔地面積,其中     床:佔4平米     衣櫃:佔2平面     餐桌:佔1.5平米 3.將以上三件傢俱新增到房子中 4.列印房子時,要求輸出:戶型,總面積,剩餘面積,傢俱名稱列表

被使用的類應該先開發

class HouseItem:     # 初始化方法     def __init__(self, name, area):         self.name = name         self.area = area

    def __str__(self):         return '[%s] 佔地 %.2f' % (self.name, self.area) """ 傢俱名稱列表 [] """ class House:     def __init__(self, house_type, area):         # 需要從外界傳遞進來的引數         self.house_type = house_type         self.area = area         # 剩餘面積(新房子沒有任何傢俱,剩餘面積=總面積)         self.free_area = area         # 傢俱名稱列表         self.item_list = []

    def __str__(self):         return '戶型:%s\n總面積:%.2f[剩餘:%.2f]\n傢俱:%s' \                % (self.house_type, self.area, self.free_area, self.item_list)

    def add_item(self, item):         print '要新增 %s' % item         """         1.判斷傢俱的面積是否超過房子的面積,如果超過了,提示不能新增這個傢俱         2.將 傢俱的名稱 追加到 傢俱名稱列表中去         3.用 房子的剩餘面積 - 傢俱的面積         """         if item.area > self.free_area:             print '%s 的面積太大了,無法新增' %item.name             # 如果不滿足,下方的程式碼就不執行             return         # 將傢俱的名稱新增到列表中         self.item_list.append(item.name)         # 計算剩餘面積         self.free_area -= item.area

# 1.建立傢俱 bed = HouseItem('bed', 400) print bed chest = HouseItem('chest', 2) print chest table = HouseItem('table', 1.5) print table

#2.建立房子物件 my_home = House('兩室一廳',60) # 新增傢俱到房子裡面去 my_home.add_item(bed) my_home.add_item(chest) my_home.add_item(table) print my_home

案例3:

需求: 1.士兵瑞恩有一把AK47 2.士兵可以開火(士兵開火扣動的是扳機) 3.槍 能夠 發射子彈(把子彈發射出去) 4.槍 能夠 裝填子彈 --增加子彈的數量

Soldier                     Gun -------------               ----------------- name                        model gun                         bullet_count #子彈數量足夠多才能完成射擊的動作 -------------               ----------------- __init__(self):            __init__(self): fire(self):                 add_bullet(self,count):#裝填子彈的方法                 shoot(self):

#練習重點:一個物件的屬性可以是另外一個類建立的物件

class Gun:     def __init__(self, model):         # 槍的型號         self.model = model         # 子彈的數量(呼叫裝填子彈的方法來增加子彈的數量)         self.bullet_count = 0

    def add_bullet(self, count):         self.bullet_count += count

    def shoot(self):         # 1.判斷子彈的數量         if self.bullet_count <= 0:             print '[%s] 沒有子彈了...' % self.model             return             # 2.發射子彈,子彈的數量-1         self.bullet_count -= 1         # 3.提示發射資訊         print '[%s] 突突突...[%d]' %(self.model,self.bullet_count) class Soldier:     def __init__(self,name):         self.name = name         """         在定義屬性的時候,如果不知道設定什麼初始值,可以設定為None         None表示什麼都沒有         表示一個空物件,沒有方法和屬性,是一個特殊的常量         可以將None賦值給任何一個變數         """         self.gun = None     def fire(self):         # 1.判斷士兵是否有槍         if self.gun == None:             print '[%s] 還沒有槍' %self.name             return         print 'go!!! [%s]' %self.name         # 士兵讓槍裝填子彈         self.gun.add_bullet(50)         # 士兵讓槍發射子彈         self.gun.shoot()

# 1.建立槍物件 ak47 = Gun('AK47') # ak47.add_bullet(50) # ak47.shoot()

# 2.建立士兵物件 ryan = Soldier('Ryan') ryan.gun = ak47 ryan.fire() #print ryan.gun

###面向物件三大特徵中的繼承:### 單繼承 繼承的概念:子類擁有父類的所有屬性和方法 繼承的語法 class 類名(父類):     def 子類特有的方法 Cat類是Animal類的子類,Animal類是Cat類的父類,Cat從Animal類繼承 Cat類是Animal類的派生類,Animal類是Cat類的基類,Cat類從Animal類派生

繼承的傳遞行,子類擁有父類的父類的屬性和方法 繼承的傳遞性:(爺爺 父親 兒子) 1.C類從B類繼承,B類又從A類繼承 2.那麼C類就具有B類和A類的所有屬性和方法 子類擁有父類以及父類的父類中封裝的所有屬性和方法 ## kt.eat() kt.drink() kt.run() kt.sleep()

# 子類繼承自父類,可以直接享受父類中已經封裝好的方法 # 子類中應該根據自己的職責,封裝子類特有的屬性和方法

class Animal(object):     def eat(self):         print '吃'     def drink(self):         print '喝'     def run(self):         print '跑'     def sleep(self):         print '睡'

class Cat(Animal):     # 子類擁有父類的所有屬性和方法     def call(self):         print '喵喵' class Hellokitty(Cat):     def speak(self):         print '我可以說日語'

# 建立一個貓物件 fentiao = Cat() fentiao.eat() fentiao.drink() fentiao.run() fentiao.sleep() fentiao.call()

#建立一個hellokitty物件 kt = Hellokitty() kt.speak() kt.call()

###重寫父類方法###     1.覆蓋父類的方法     2.擴充套件父類的方法 class Animal:     def eat(self):         print '吃' class Cat(Animal):     # 子類擁有父類的所有屬性和方法     def call(self):         print '喵喵'

class Hellokitty(Cat):     def speak(self):         print '我可以說日語'     def call(self):         # 針對子類特有的需求,編寫程式碼         print '歐哈有~空你起哇'         # 呼叫原本在父類中封裝的程式碼         Cat.call(self)         # 增加其他的子類程式碼         print '#[email protected][email protected]!#!#' kt = Hellokitty() kt.call()

下圖可以看出: 如果子類中,重寫了父類的方法,在執行中,只會呼叫在子類中重寫的父類的方法而不會呼叫父類的方法

輸出結果:

如果子類呼叫父類,則同時會輸出自己的方法和夫類的

結果如下圖:

練習:

class Bird:     def __init__(self):         self.hungry = True     # 鳥吃過了以後就不餓了     def eat(self):         if self.hungry:             print 'Aaaaahhh...'             self.hungry = False         else:             print 'No thanks'

class SongBird(Bird):     def __init__(self):         self.sound = 'Squawk!'         Bird.__init__(self)     def sing(self):         print self.sound

littlebird = SongBird() littlebird.eat() littlebird.sing()

###多繼承###

class A:     def test(self):         print 'A-----test 方法'     def demo(self):         print 'A-----demo 方法' class B:     def test(self):         print 'B------test 方法'     def demo(self):         print 'B-------demo方法' class C(B,A):     """多繼承可以讓子類物件,同時具有多個父類的屬性和方法"""     pass

# 建立子類物件 c = C() c.test() c.demo()

注意:當多繼承時,子類括號中誰在前面就呼叫誰的方法

###新式類和舊式類### 新式類和舊式(經典)類: object是Python為所有物件提供的基類,提供有一些內建的屬性和方法,可以使用dir函式檢視 新式類:以object為基類的類,推薦使用 經典類:不以object為基類的類,不推薦使用 在python3.X中定義的類時,如果沒有指定父類,會預設使用object作為基類--python3.x中定義的類都是新式類 在python2.x中定義類時,如果沒有指定父類,則不會以object作為基類 ####推薦使用新式類#############

新式類和舊式類在多繼承時---會影響到方法的搜尋順序

為保證編寫的程式碼能夠同時在python2.x和python3.x執行 今後在定義類時,如果沒有父類,建議統一繼承自object

###繼承(私有屬性和私有方法)###  類的私有屬性和私有方法 1.子類物件不能在自己的方法內部,直接訪問父類的私有屬性和私有方法 2.子類物件可以通過父類的公有方法間接訪問到私有屬性或私有方法 私有屬性,私有方法是物件的隱私,不對外公開,外界以及子類都不能直接訪問 私有屬性,私有方法常用做一些內部的事情

class A:     def __init__(self):         # 在初始化方法中定義兩個屬性,一個公有屬性一個私有屬性         self.num1 = 100         self.__num2 = 200

    def __test(self):         print '私有方法 %d %d' % (self.num1, self.__num2)

    def test(self):         print '父類的共有方法 %d' % self.__num2         self.__test()

class B(A):     def demo(self):         # # 在子類的物件方法中,不能訪問父類的私有屬性         # print '訪問父親的私有屬性 %d' % self.__num2         # # 在子類物件的方法中,不能呼叫父類的私有方法         # self.__test()         #呼叫父類的共有方法         self.test()

# 建立一個子類物件 b = B() b.demo() # b.test() # 在外界不能直接訪問物件的私有屬性/呼叫私有方法 # print b.__num2 # b.__test()

###在此可以看出,要顯示訪問物件的私有方法或屬性時,可以建立共有方法後,將私有方法新增進去,最後直接呼叫共有方法即可###

###綜合練習( 圖書管理系統)###  圖書管理系統功能:                     1. 查詢                     2. 增加                     3. 借閱                     4. 歸還                     5. 退出 class Book(object):     def __init__(self, name, author, state, bookIndex):         self.name = name         self.author = author         # 0:借出 1:未借出         self.state = state         self.bookIndex = bookIndex

    # 列印物件時自動呼叫;str(物件)     def __str__(self):         return "書名:<%s> 狀態:<%s>" % (self.name, self.state) class BookManage(object):     books = []

    def start(self):         """圖書管理初始化"""         b1 = Book('python', 'Guido', 1, "INS888")         self.books.append(b1)         self.books.append(Book('java', 'hello', 1, "IGS888"))         self.books.append(Book('c', 'westos', 1, "INS880"))

    def Menu(self):         self.start()         while True:             print("""                         圖書管理系統                     1. 查詢                     2. 增加                     3. 借閱                     4. 歸還                     5. 退出

             """)

            choice = input("Choice:")             if choice == "1":                 pass             elif choice == '2':                 self.addBook()             elif choice == '3':                 self.borrowBook()             else:                 print("清輸入正確的選擇!")

    def addBook(self):         name = input("書名:")         self.books.append(Book(name, input("作者:"), 1, input("書籍位置:")))         print("新增圖書%s成功!" % (name))

    def borrowBook(self):         name = input("借閱書籍名稱:")         ret = self.checkBook(name)         if ret != None:             if ret.state == 0:                 print("書籍《%s》已經借出" % (name))             else:                 ret.state = 0                 print("借閱%s成功" % (name))         else:             print("書籍《%s》不存在!" % (name))

    def checkBook(self, name):         """查詢書籍是否存在"""         for book in self.books:             # book: Book類建立的物件             # book.name;             if book.name == name:                 # 返回book物件                 return book         else:             return None

bookManage = BookManage() bookManage.Menu()