1. 程式人生 > >Python之面向物件(1)

Python之面向物件(1)

知識框架:

1.面向過程vs面向物件

2.初識面向物件
      類的相關知識
      物件的相關知識
      面向物件相關介紹

3.面向物件的三大特性
      繼承
      多型
      封裝

4.面向物件的更多說明

      面向物件的軟體開發
      幾個概念的說明
      面向物件常用術語

面向過程VS面向物件

面向過程強調的是怎麼做?

面向過程的程式設計的核心是過程(流水線式思維),過程即解決問題的步驟,面向過程的設計就好比精心設計好一條流水線,考慮周全什麼時候處理什麼東西。把完成某一個需求的所有步驟從頭到尾逐步實現,根據開發需求,將某些功能獨立的程式碼,封裝成一個又一個函式,最後完成的程式碼是:順序呼叫不同的函式。

 

優點是:極大的降低了寫程式的複雜度,注重步驟與過程不注重職責分工,只需要順著要執行的步驟,堆疊程式碼即可。

 

缺點是:一套流水線或者流程就是用來解決一個問題,程式碼牽一髮而動全身,如果需求複雜 程式碼會變得複雜,開發複雜專案沒有固定的套路 開發難度大。

面向物件強調誰來做?

面向物件的程式設計的核心是物件(上帝式思維),要理解物件為何物,必須把自己當成上帝,上帝眼裡世間存在的萬物皆為物件,不存在的也可以創造出來。相比較函式,面向物件是更大的封裝,根據職責在一個物件中封裝多個方法,在完成某一個需求之前,首先確定職責--要做的事情(方法)根據職責 確定不同的物件,在物件內部封裝不同的方法,最後完成的程式碼 就是順序的讓不同的物件呼叫不同的方法。

優點是:解決了程式的擴充套件性。對某一個物件單獨修改,會立刻反映到整個體系中,如對遊戲中一個人物引數的特徵和技能修改都很容易。

 

缺點:可控性差,無法向面向過程的程式設計流水線式的可以很精準的預測問題的處理流程與結果,面向物件的程式一旦開始就由物件之間的互動解決問題

即便是上帝也無法預測最終結果。於是我們經常看到一個遊戲人某一引數的修改極有可能導致陰霸的技能出現,一刀砍死3個人,這個遊戲就失去平衡。

初識類和物件

python中一切皆為物件

是具有相同特徵或者行為的事物的一個統稱,是抽象的不能直接使用。
   特徵,被稱為屬性;
   行為,被稱為方法;
   類的三要素: 類名 屬性 方法
類名的確定,名詞提煉法,分析整個業務流程出現的名詞,通常就是找到的類,對物件的特徵描述通常可以定義為屬性,物件具有的行為通常可以定義成方法。物件由類創建出來的一個具體存在 可以直接使用。

舉一個栗子:比如你現在有一個動物園,你想描述這個動物園,那麼動物園裡的每一種動物就是一個類,老虎、天鵝、鱷魚、熊。他們都有相同的屬性,比如身高體重出生時間和品種,還有各種動作,比如鱷魚會游泳,天鵝會飛,老虎會跑,熊會吃。

但是這些老虎熊啥的都不是具體的某一隻,而是一類動物。雖然他們都有身高體重,但是你卻沒有辦法確定這個值是多少。如果這個時候給你一隻具體的老虎,而你還沒死,那你就能給他量量身高稱稱體重,這些數值是不是就變成具體的了?那麼具體的這一隻老虎就是一個具體的例項,也是一個物件。不止這一隻,其實每一隻具體的老虎都有自己的身高體重,那麼每一隻老虎都是老虎類的一個物件。

在python中,用變量表示特徵,用函式表示技能,因而具有相同特徵和技能的一類事物就是‘類’,物件是則是這一類事物中具體的一個。

 

 

類的相關知識

 

類的宣告

 
'''class 類名:    '類的文件字串'    類體'''

#建立一個類
class Data:  
   pass

 

類的兩種作用:屬性引用和例項化
 

 屬性引用(類名.屬性)

#定義一個人類
class Person:
    # 人的角色屬性都是人
    role = 'person'
    # 人都可以走路,也就是有一個走路方法
    def walk(self):  
        print("person is walking...")
#檢視人的role屬性
print(Person.role)
# 引用人的走路方法,注意,這裡不是在呼叫
print(Person.walk) 
 

例項化:類名加括號就是例項化,會自動觸發__init__函式的執行,
可以用它來為每個例項定製自己的特徵 
       

class Person:
    # 人的角色屬性都是人
    role = 'person'

    def __init__(self, name):
        # 每一個角色都有自己的暱稱;
        self.name = name
    # 人都可以走路,也就是有一個走路方法
    def walk(self):  
        print("person is walking...")
 # 檢視人的role屬性
print(Person.role) 
# 引用人的走路方法,注意,這裡不是在呼叫
print(Person.walk)  

例項化的過程就是類——>物件的過程

原本我們只有一個Person類,在這個過程中,產生了一個egg物件,有自己具體的名字、攻擊力和生命值。

語法:物件名 = 類名(引數)

egg = Person('egon')  
#類名()就等於在執行Person.__init__()
#執行完__init__()就會返回一個物件。
這個物件類似一個字典,
存著屬於這個人本身的一些屬性和方法。

檢視屬性&呼叫方法

print(egg.name)     
#檢視屬性直接 物件名.屬性名

print(egg.walk())
#呼叫方法,物件名.方法名()

 

關於self

 

Python編寫類的時候,每個函式引數第一個引數都是self,一開始我不管它到底是幹嘛的,只知道必須要寫上。後來對Python漸漸熟悉了一點,再回頭看self的概念,似乎有點弄明白了。

首先明確的是self只有在類的方法中才會有,獨立的函式或方法是不必帶有self的。self在定義類的方法時是必須有的,雖然在呼叫時不必傳入相應的引數。

self在例項化時自動將物件/例項本身傳給__init__的第一個引數,你也可以給他起個別的名字,建議不要改,因為別人看不懂

 

 

物件的相關知識

 

#定義一個人類
class Person:  
      role = 'person'  
    def __init__(self, name, aggressivity, life_value):
        self.name = name
        # 每一個角色都有自己的攻擊力;
        self.aggressivity = aggressivity  
        # 每一個角色都有自己的生命值;
        self.life_value = life_value  
    def attack(self,dog):  
    # 人可以攻擊狗,這裡的狗也是一個物件。
   #人攻擊狗,那麼狗的生命值就會
   根據人的攻擊力而下降
        dog.life_value -= self.aggressivity

 

物件是關於類而實際存在的一個例子,即例項

 

物件/例項只有一種作用:屬性引用

 

egg = Person('egon', 10, 1000)
print(egg.name)
print(egg.aggressivity)
print(egg.life_value)

當然了,你也可以引用一個方法,因為方法也是一個屬性,只不過是一個類似函式的屬性,我們也管它叫動態屬性。
引用動態屬性並不是執行這個方法,要想呼叫方法和呼叫函式是一樣的,都需要在後面加上括號。

 

print(egg.attack)

 

面向物件小結

 

class 類名:
    def __init__(self, 引數1, 引數2):
        self.物件的屬性1 = 引數1
        self.物件的屬性2 = 引數2

    def 方法名(self): pass

    def 方法名2(self): pass

物件名 = 類名(1, 2)  
#物件就是例項,代表一個具體的東西
# 類名():類名+括號就是例項化一個類,
相當於呼叫了__init__方法
# 括號裡傳引數,引數不需要傳self,
其他與init中的形參一一對應
# 結果返回一個物件
物件名.物件的屬性1 
#檢視物件的屬性,
直接用 物件名.屬性名 即可
物件名.方法名()  
#呼叫類中的方法,
直接用 物件名.方法名() 即可

 

 

面向物件的相關介紹

 

初始化方法 _ _init_ _

 

當使用 類名() 建立物件的時候 會自動執行以下操作:
1.為物件 在記憶體中分配空間 -- 建立物件
2.為物件的屬性設定初始值 ---初始化方法
這個初始化方法就是 __init__方法 是物件的內建方法 ,__init__ 是用來專門定義一個類 具有哪些屬性的方法。

 

在初始化方法中 定義屬性

 

在__init__ 方法內部使用 self.屬性名=屬性的初始值 ,就可以定義屬性,定義屬性以後 在使用類建立的物件都會擁有該屬性。

class Cat:
    def __init__(self):
        print("這是一個初始化方法")
        #在初始化方法中 定義屬性
        self.name = "貓"  
   #使用類名()建立物件的時候會自動呼叫
    初始化方法__init__
    def eat(self):
        print("%s愛吃魚" % self.name)

tom = Cat()
print(tom.name)


使用引數設定屬性初始值

在開發中 如果希望  建立物件的同時,就設定物件的屬性,可以對__init__進行改造。
1. 把希望設定的屬性值 定義成__init__ 方法的引數
2.方法內部使用 self.屬性=形參 接受外部傳遞的引數
3.在建立物件時 使用 類名(屬性1,屬性2...)呼叫
 

class Cat:
    def __init__(self, new_name):
        # self.name="貓"#這個值是固定死的
        self.name = new_name
    def eat(self):
        print("%s愛吃魚" % self.name)

tom = Cat("小花貓")
print(tom.name)
lazy_cat = Cat("愛吃魚")
lazy_cat.eat()


_ _del_ _

當使用 類名()建立物件時 物件分配完空間後 自動呼叫 __init__ 方法,當一個物件從記憶體中銷燬前 會自動呼叫 __del__ 方法。

_ _str_ _方法

在python中 使用print 輸出物件變數 預設情況下 會輸出這個變數 引用的物件
是由哪一類建立的物件 以及在記憶體中的地址(十六進位制表示)。如果在開發中 希望 print 輸出物件 變數時 能夠列印 自定義的內容 可以使用__str__。
__str__ 必須返回一個字串
 

class Cat:
    def __init__(self,new_name):
        self.name=new_name
        print("%s 來了"%self.name)
    def __del__(self):
        print("%s 我去了"%self.name)
    def __str__(self):
        #必須返回一個字串
      return "love[%s]"%self.name
#tom 是一個全域性變數
tom=Cat("Ahab")
print(tom)

 

文章首發自公眾號【Ahab雜貨鋪】關注公眾號技術分享第一時間送達!