面向對象編程思想
- 面向對象是一門編程思想,編程思想僅僅是一門思想,與任何技術無關
- 核心是對象兩字,對象能夠理解爲特徵與技能的結合體
- 基於該編程思想編寫程序,就比如創造世界,一種造物主的思惟方式
- 優勢:可擴張性強
- 缺點:編寫程序的複雜難度比面向過程高
以上都是純理論,理解下用本身的話能編出來就行,下面來講說核心對象html
在現實世界中,經過一個個的對象,根據相同的特徵和行爲,再分門別類。python
可是在程序中,必須先有類,再經過調用類,建立對象。編程
那麼,我們如何定義類,又如何建立對象呢?(暫時仍是先說理論吧,否則看代碼,估計直接懵逼了……)markdown
關於類的致命三問:什麼是類?有什麼用?怎麼使用?函數
-
類的定義:就是類型、類別,跟現實的分類相似。是一系列對象之間相同特徵和行爲(技能)的結合體post
-
類的做用:我的理解,就是爲了建立對象用的。學習
(終於要寫代碼了,哈哈哈哈哈哈哈)url
- 類的語法:
class 類名: 特徵 # 在python 中,用變量來表示特徵 行爲 # 在python 中,用函數來表示行爲,也就是你們所說的技能
如今,咱們來寫一我的類,人類的特徵有名字,年齡,性別,行爲有吃飯,跑步,玩,擼代碼了!spa
""" 人類 特徵:名字、年齡、性別 行爲:吃飯、跑、玩 """ class Person: # 這些都是人的特徵 name = "dawn" # 姓名 age = 27 # 年齡 sex = "男" # 性別 # 這些都是人的行爲(技能) def eat(self): # 吃飯 print("民以食爲天o(∩_∩)o 哈哈") def run(self): # 跑步 print("英雄救美,不存在的!別慫!趕忙跑!!!") def play(self): # 玩 print("大爺!歡迎下次來玩兒啊!") print(Person) print(Person.name) print(Person.play)
輸出結果3d
<class '__main__.Person'> # Person 的打印結果 dawn # Person.name 的打印結果 <function Person.play at 0x0000022E54FA7DC8> # Person.play 的打印結果
瞅了這麼久,發現了嗎?類名,類的行爲,類的屬性都是咋用的?(理論又來了~~~)
- 類名的命名規範:使用駝峯命名法,即單詞的首字母得大寫!
- 類提供了一種便捷的獲取名字的方式,就是
類名.名字
。類的名字包含特徵和行爲。我們將類的特徵稱之爲屬性,類的行爲稱之爲方法 - 在類的內部定義函數(也就是行爲的時候,默認有一個參數
self
),這個是幹啥的,等會說
經過輸出的內容來看,類名指向的是類的內存地址。如何來查看類的名稱空間呢?看代碼……
print(Person.__dict__)
輸出結果
{'__module__': '__main__', 'name': 'dawn', 'age': 27, 'sex': '男', 'eat': <function Person.eat at 0x00000228C1683558>, 'run': <function Person.run at 0x00000228C1683B88>, 'play': <function Person.play at 0x00000228C1687DC8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
驚不驚喜!意不意外!對,這就是Person類的名稱空間中的內容!!!也就是說類的名稱空間是在定義階段產生
到這裏,我們就該聊聊類是如何使用的了。前面咱就說了,類的調用就是對象的建立。說的類的使用就得知道對象是啥了!耐心點,好玩的還在後面!
哈哈哈哈哈!我三連問回來啦!——什麼是對象?有什麼用?怎麼使用?
-
對象的定義:特徵與技能的結合體
-
語法:
類名()
我們來瞅瞅對象是如何建立的,類又是如何調用的 !
# 上面咱定義了一個Person類,這裏直接拿來用 # 調用Person類後會產生一個對象,使用一個變量接收 p1 = Person() # 輸出p1 的屬性 print(p1.name, p1.age, p1.sex) # 使用p1 的方法 p1.play() p1.run() p1.eat()
輸出結果
dawn 27 男 # p1的屬性 大爺!歡迎下次來玩兒啊! # p1.play()的結果 英雄救美,不存在的!別慫!趕忙跑!!! # p1.run()的結果 民以食爲天o(∩_∩)o 哈哈 # p1.eat()的結果
剛剛獲取了對象的屬性(也就是查詢),發現沒有,這些屬性都是類的,咱們可否對對象的屬性作個增刪改呢?若是修改了對象的屬性,類是否隨之改變呢?動手試試
修改對象的屬性,其實就是對象本身增長了屬性
# 修改屬性 print(Person.__dict__) # 修改前,Person的名稱空間 print(p1.__dict__) # 修改前,p1的名稱空間 p1.name = "haha" # 修改對象的name 屬性,其實是p1對象本身新增了name 屬性 print(Person.__dict__) # 修改後,Person的名稱空間 print(p1.__dict__) # 修改後,p1的名稱空間
輸出結果
增長對象的屬性
# 增長屬性 print(p1.__dict__) print(Person.__dict__) p1.hobby = "read" print(p1.__dict__) print(Person.__dict__)
輸出結果
刪除對象的屬性
# 刪除屬性 del p1.sex print(p1.sex) print(Person.__dict__)
輸出結果
縱觀以上的結果,咱說了那些屬性都在類的名稱空間裏,那麼有沒有什麼方法,讓這些屬性是經過對象來增刪改查的呢?
固然有的啦!那就是__init__()
!咱們來看看使用方式
# 定義一個類 class Person: # 這些都是人的特徵 name = "dawn" # 姓名 # __init__() def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex # 這些都是人的行爲(技能) def eat(self): # 吃飯 print("民以食爲天o(∩_∩)o 哈哈") # 經過類建立兩個對象,分別是p1和p2 p1 = Person("haha", 39, "男") p2 = Person("lee", 21, "女") # 查看Person類的名稱空間 print(Person.__dict__) # 查看對象p1的名稱空間 print(p1.__dict__) # 查看對象p2的名稱空間 print(p2.__dict__)
輸出結果
發現什麼了沒有?
__init__()
實現了對象的個性化定製,並且建立對象在傳參時,沒有傳self這個參數。
那是由於__init__()
在調用時,會將對象自己做爲第一個參數傳入。緣由後期學習之後,才知道。如今就作一個總結好了
- 由對象來調用類的內部函數,稱爲對象的綁定方法。對象的綁定方法特殊之處在於:會將對象自己看成第一個參數傳入方法(咱能夠回頭看看定義類的時候,是否是每一個行爲也就是方法,都有self參數)
__init__()
在調用類時觸發,會作如下事情:- 將對象自己看成第一個參數傳入方法(緣由:對象的綁定方法)
- 調用時,傳入的其餘參數一併被
__init__()
接收
接着,咱們來看看,對象是如何對屬性作增刪改查的
# 獲取p1的屬性 print(f"姓名:{p1.name},性別:{p1.sex},年齡:{p1.age}") # 修改p1的屬性 print(f"修改前,p1的名稱空間:{p1.__dict__}") p1.age = 27 print(f"修改後,p1的屬性值:{p1.age}") print(f"修改後,p1的名稱空間:{p1.__dict__}")
輸出結果
再來看看增長(前面就已經舉例了,算了仍是再舉一個吧)和刪除
# 獲取p1的屬性 print(f"姓名:{p1.name},性別:{p1.sex},年齡:{p1.age}") # 增長屬性 print(f"增長hobby前:{p1.__dict__}") p1.hobby = "read" print(f"hobby的取值:{p1.hobby}") print(f"增長hobby後:{p1.__dict__}") # 刪除屬性 print(f"刪除sex前:{p1.__dict__}") del p1.sex print(f"刪除sex後:{p1.__dict__}")
輸入結果
還有個地方,就是咱剛纔一直在說名稱空間,那麼類的名稱空間和對象的名稱空間,有什麼關係呢?
我們繼續看代碼
# 經過類建立一個對象 p1 = Person("haha", 39, "男") # 查看Person類的名稱空間和屬性 print(f"Person的名稱空間:{Person.__dict__}") print(f"Person的name屬性值:{Person.name}") # 查看對象p1的名稱空間和屬性 print(f"p1的名稱空間:{p1.__dict__}") print(f"p1的name屬性值:{p1.name}") # 刪除p1的屬性name,再打印p1的名稱空間和屬性 del p1.name print(f"刪除name屬性後,p1的名稱空間:{p1.__dict__}") print(f"刪除name屬性後,p1的name屬性值:{p1.name}")
輸出結果
看到沒?對象的屬性刪除後,再去調用這個屬性,並無報錯,而是將類中的同名屬性值獲取了過來
那若是類中沒有這個屬性呢?咱們再來看看
class Person: # 這些都是人的特徵 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex # 經過類建立一個對象 p1 = Person("haha", 39, "男") # 查看對象p1的名稱空間和屬性 print(f"p1的名稱空間:{p1.__dict__}") print(f"p1的name屬性值:{p1.name}") # 刪除p1的屬性name,再打印p1的名稱空間和屬性 del p1.name print(f"刪除name屬性後,p1的名稱空間:{p1.__dict__}") print(f"刪除name屬性後,p1的name屬性值:{p1.name}")
輸出結果
報錯了!!!由此咱們能夠總結下:
對象先從自身名稱空間查找,沒有就去類的名稱空間查找,再沒有就會報錯。
對象名字的查找順序:
對象自身 ----→ 類 ----→ 都沒有,報錯
定義類及調用的固定模式
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 #查看對象的屬性,直接用 對象名.屬性名 便可 對象名.方法名() #調用類中的方法,直接用 對象名.方法名() 便可