Python面向物件OOP 筆記
面向過程:
1.把需要完成需求的方法都設計出來
2.能獨立封裝的程式碼都獨立封裝成每一個方法
3.按順序呼叫這些方法
面向物件:
基於面向過程更高階的封裝
1.完成需要前明確職責
2.根據職責建立不同物件,在不同物件中設計需要實現的方法
3.按順序讓不同的物件呼叫不同的方法
舉個例子,比如一個家裡有爸爸媽媽和小明,我們在這裡設計每個人(即每個物件)的需求都不一樣。爸爸需要做飯,打掃衛生,接送小明上下學(3個不同的方法),媽媽需要做飯,打掃衛生,上班賺錢(同樣3個方法),小明需要完成作業,玩耍,以及去上學(也是3個方法)。
如果按時間順序來看,爸爸的一天應該是:先起床做飯,送小明上學,回家打掃衛生,做飯,接小明放學。每個方法輪流呼叫,這就是面向過程
同理,媽媽和小明的一天也是一個呼叫順序的面向過程。
在這個家裡我們需要明確每個人的分工和職責,比如說做飯和打掃衛生是爸爸和媽媽都擁有的方法,而對爸爸來說,接送小明上下學就是他特有的方法,這件事只有他能完成,對媽媽來說就是上班賺錢,對小明來說就是完成作業、玩耍和上學。而一個家庭的正常運轉,需要每個人都在自己的位置上完成自己特有的封裝方法。我們把一個家庭運轉當成需要完成的需求,那麼一個家裡需要每個成員都各司其職,把這些物件(爸爸、媽媽和小明)都封裝起來,再抽象出一個家庭的類,那麼每次新建一個家庭類,都必須要有以上三個物件,而我們要從每個物件中呼叫各自特有的方法讓這個家庭正常運轉起來,這就是面向物件
類 就相當於一個模板 我們可以用類來建立物件
比如說把爸爸的行為定義為一個父親類Class Dad,那麼每次建立一個爸爸,只要new Dad()就可以創建出來。(Python裡面建立物件只需直接呼叫類名
而初始化一個物件的時候一般都會有這個物件的基本屬性,比如說我建立一個人的類,那麼基本屬性一般是姓名、身高、體重,這個人有的行為方法,可以是吃、喝、睡。
Python中的init方法就是初始化方法,物件被初始化時會被自動呼叫,類似於C++中的構造方法。
示例:
#!/usr/bin/python3 # coding=utf-8 #object類是基類 class Person: def__init__(self,name,age,height): self.name = name self.age = age self.height = height def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(xiaoming) xiaoming.eat() print(xiaoming.name) print(xiaoming.age)
執行結果如下:
除了init以外還有幾個基礎的方法:
new方法在建立的時候就會被呼叫,而del方法是物件在記憶體中被銷燬時會被自動呼叫,str是返回物件的描述資訊。
在剛才的程式碼上我們修改一下輸出:
#!/usr/bin/python3 # coding=utf-8 #object類是基類 class Person: def __init__(self,name,age,height): self.name = name self.age = age self.height = height def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(Person) print(xiaoming)
這時候打印出來的就是:
可以看出物件xiaoming打印出來的是所在類(object是預設基類),以及0x000002509A5408D0 xiaoming這一物件所在的記憶體地址。
這裡我們寫一個str方法就能觀察出來對物件的資訊描述:
#!/usr/bin/python3 # coding=utf-8 #object類是基類 class Person: def __init__(self,name,age,height): self.name = name self.age = age self.height = height #物件返回的資訊描述:就是這個物件輸出的時候,可以列印它的相關資訊。 def __str__(self): return 'I am a str method.' def run(self): print('I can run.') def eat(self): print('I can eat.') xiaoming = Person('xiaoming',18,180) print(Person) print(xiaoming)
這時再列印輸出,會發現物件xiaoming輸出的是我們在str方法內返回的對xiaoming的描述:
傳入的初始化引數內包括預設引數,即需要一開始就賦值,這樣往後建立物件時,如果物件沒有給這個變數傳參,也不影響執行。
比如這裡傳入引數house:
def __init__(self,name,age,height,house=None): self.name = name self.age = age self.height = height self.house = house
然後新建兩個物件,針對house引數一個賦值一個不賦值:
xiaoming = Person('xiaoming',18,180,'公寓') print(xiaoming.house) xiaohong = Person('xiaohong',17,170) print(xiaohong.house)
執行結果:
del方法則是在在物件銷燬時會呼叫一次:
#!/usr/bin/python3 # coding=utf-8 #object類是基類 class Person: def __init__(self,name,age,height,house=None): self.name = name self.age = age self.height = height self.house = house #物件返回的資訊描述:就是這個物件輸出的時候,可以列印它的相關資訊。 def __str__(self): return 'I am a str method.' def run(self): print('I can run.') def eat(self): print('I can eat.') #物件結束就會呼叫 def __del__(self): print('over') xiaoming = Person('xiaoming',18,180,'公寓') print(xiaoming.house) xiaohong = Person('xiaohong',17,170) print(xiaohong.house)
執行結果如圖,第一個over是xiaoming結束時銷燬呼叫del方法,第二個over時xiaohong結束時呼叫del方法。
面向物件練習
設計類的時候應該優先設計不需要依賴他人就能獨立存在的類,所以應該先開發傢俱類。
#!/usr/bin/python3 # coding=utf-8 class HouseItem: def __init__(self,name,area): self.name = name self.area = area def __str__(self): return '[%s]佔地面積 %.2f' %(self.name ,self.area) #建立傢俱 bed = HouseItem('席夢思',4) chest = HouseItem('衣櫃',2) table = HouseItem('餐桌',1.5) print(bed) print(chest) print(table)
執行如下:
完善房子類:
#!/usr/bin/python3 # coding=utf-8 class HouseItem: def __init__(self,name,area): self.name = name self.area = area def __str__(self): return '[%s]佔地面積 %.2f' %(self.name ,self.area) #建立傢俱 bed = HouseItem('席夢思',4) chest = HouseItem('衣櫃',2) table = HouseItem('餐桌',1.5) print(bed) print(chest) print(table) class House: def __init__(self,house_type,area,item_list=[]): self.house_type = house_type self.area = area self.free_area = area self.item_list = item_list def __str__(self): return '%s 剩餘的面積是 %.2f,擁有傢俱%s' \ %(self.house_type,self.free_area,self.item_list) def add_item(self,item): #1.判斷傢俱面積是否大於房間剩餘面積 if item.area > self.free_area: return '不能放傢俱啦' #2.置放傢俱 self.item_list.append(item.name) self.free_area -= item.area my_house = House('兩室一廳',60) my_house.add_item(bed) my_house.add_item(table) print(my_house)
這裡需要注意的是,如果在置放傢俱一行程式碼中append的是item而不是item.name,那麼執行返回的是item的記憶體地址。
最後執行結果: