1.1類和對象
1.1.1萬物皆對象

分類是人們認識世界的一個很自然的過程,在日常生活中會不自覺地將對象進行進行分類
對象歸類
- 類是抽象的概念,僅僅是模板 比如說:“人”
- 對象是一個你能夠看得到、摸得著的具體實體: 趙本山,劉德華,趙麗穎
舉例
user1 = 'zhangsan'
print(type(user1))
user2 = 'lisi'
print(type(user2))
輸出
<class 'str'>
<class 'str'>
以上str是類(python中的字符串類型),user1和user2是對象(以前我們叫變量)
研究對象

顧客類型
屬性:
姓名—張浩
年齡—20
體重—60kg
行為:
購買商品

收銀員類型
屬性:
員工號—10001
姓名—王淑華
部門—財務(wù)部
行為:
收款
打印賬單
1.1.2 對象的特征——屬性
屬性——對象具有的各種特征。 每個對象的每個屬性都擁有特定值。 例如:顧客張浩和李明的年齡、姓名不一樣。
1.1.4 對象的特征——方法(操作,行為)
方法——對象執(zhí)行的操作(通常會改變屬性的值)。 顧客對象的方法---購買商品。 收銀員對象的方法----收款。
對象:用來描述客觀事物的一個實體,由一組屬性和方法構(gòu)成
例子

類型:狗
對象名:doudou
屬性:
顏色:白色
方法:
叫,跑,吃
對象同時具有屬性和方法兩項特性。 對象的屬性和方法通常被封裝在一起,共同體現(xiàn)事物的特性, 二者相輔相承,不能分割。
1.1.4 從對象抽象出“類”
抽取出下列對象的共同特征(屬性和方法)


類是模子,定義對象將會擁有的特征(屬性)和行為(方法)。
再次強調(diào)
- 類是抽象的概念,僅僅是模板。 比如說:“人”, 類定義了人這種類型屬性(name,age...)和方法(study,work...)。
- 對象是一個你能夠看得到、摸得著的具體實體: 趙本山,劉德華,趙麗穎,這些具體的人都具有人類型中定義的屬性和方法,不同的是他們各自的屬性不同。
根據(jù)類來創(chuàng)建對象被稱為實例化。
1.2 類的定義
1.2.1 定義只包含方法的類
在 Python 中要定義一個只包含方法的類,語法格式如下:
class 類名:
def 方法1(self, 參數(shù)列表):
pass
def 方法2(self, 參數(shù)列表):
pass
方法 的定義格式和之前學(xué)習過的函數(shù) 幾乎一樣。 區(qū)別在于第一個參數(shù)必須是 self。
1.2.2 創(chuàng)建對象
當一個類定義完成之后,要使用這個類來創(chuàng)建對象,語法格式如下:
對象變量 = 類名()
第一個面向?qū)ο蟪绦?/p>
需求:
- 小貓 愛 吃 魚,小貓 要 喝 水。
分析:
- 定義一個貓類
Cat。 - 定義兩個方法
eat和drink。
class Cat:
"""這是一個貓類"""
def eat(self):
print("小貓愛吃魚")
def drink(self):
print("小貓在喝水")
tom = Cat()
tom.drink()
tom.eat()
使用 Cat 類再創(chuàng)建一個對象
lazy_cat = Cat()
lazy_cat.eat()
lazy_cat.drink()
1.3 self 參數(shù)
我們在調(diào)用對象的方法是不需要傳遞self參數(shù),這個self參數(shù)是系統(tǒng)自動傳遞到方法里的。
1.3.1 給對象增加屬性
在 Python 中,要 給對象設(shè)置屬性,非常的容易,但是不推薦使用。 因為:對象屬性的封裝應(yīng)該封裝在類的內(nèi)部。 要 給對象設(shè)置屬性,只需要在 類的外部的代碼 中直接通過.設(shè)置一個屬性即可
tom.name = "Tom"
lazy_cat.name = "大懶貓"
1.3.2 理解self到底是什么
class Cat:
"""這是一個貓類"""
def eat(self):
print(f"小貓愛吃魚,我是{self.name},self的地址是{id(self)}")
def drink(self):
print("小貓在喝水")
tom = Cat()
print(f'tom對象的id是{id(tom)}')
tom.name = "Tom"
tom.eat()
print('-'*60)
lazy_cat = Cat()
print(f'lazy_cat對象的id是{id(lazy_cat)}')
lazy_cat.name = "大懶貓"
lazy_cat.eat()
輸出
tom對象的id是36120000
小貓愛吃魚,我是Tom,self的地址是36120000
------------------------------------------------------------
lazy_cat對象的id是36120056
小貓愛吃魚,我是大懶貓,self的地址是36120056
由輸出可見,當我們使用的時候,python會自動將x對象做為實參傳給x方法的self參數(shù)。 也可以這樣記憶,誰點(.)的方法,self就是誰。
x對象.x方法()
類中的每個實例方法的第一個參數(shù)都是self
1.4 初始化方法init()
初始化方法
- 當使用
類名()創(chuàng)建對象時,會自動 執(zhí)行以下操作:
1.為對象在內(nèi)存中 分配空間 —— 創(chuàng)建對象(調(diào)用__new__)
2.為對象的屬性 設(shè)置初始值 —— 初始化方法(調(diào)用__init__并且將第一步創(chuàng)建的對象,通過self參數(shù)傳給__init__) - 這個 初始化方法 就是
__init__方法,__init__是對象的內(nèi)置方法(有的書也叫魔法方法,特殊方法)
__init__方法是 專門 用來定義一個類 具有哪些屬性并且給出這些屬性的初始值的方法!
在 Cat 中增加__init__方法,驗證該方法在創(chuàng)建對象時會被自動調(diào)用
class Cat:
"""這是一個貓類"""
def __init__(self):
print("初始化方法")
- 在初始化方法內(nèi)部定義屬性
在__init__方法內(nèi)部使用 self.屬性名 = 屬性的初始值 就可以 定義屬性
定義屬性之后,再使用 Cat類創(chuàng)建的對象,都會擁有該屬性
class Cat:
def __init__(self):
print("這是一個初始化方法")
# 定義用 Cat 類創(chuàng)建的貓對象都有一個 name 的屬性
self.name = "Tom"
def eat(self):
print("%s 愛吃魚" % self.name)
# 使用類名()創(chuàng)建對象的時候,會自動調(diào)用初始化方法 __init__
tom = Cat()
tom.eat()
改造初始化方法 —— 初始化的同時設(shè)置初始值
- 在開發(fā)中,如果希望在 創(chuàng)建對象的同時,就設(shè)置對象的屬性,可以對
__init__方法進行 改造
- 把希望設(shè)置的屬性值,定義成
__init__方法的參數(shù) - 在方法內(nèi)部使用
self.屬性 = 形參接收外部傳遞的參數(shù) - 在創(chuàng)建對象時,使用
類名(屬性1, 屬性2...)調(diào)用
class Cat:
def __init__(self, name):
print("初始化方法 %s" % name)
self.name = name
tom = Cat("Tom")
lazy_cat = Cat("大懶貓")
1.5_str_ 方法
在 Python 中,使用 print 輸出 對象變量,默認情況下,會輸出這個變量的類型,以及 在內(nèi)存中的地址(十六進制表示)
class Cat:
def __init__(self, new_name):
self.name = new_name
print("%s 來了" % self.name)
tom = Cat("Tom")
print(tom)
輸出
Tom 來了
<__main__.Cat object at 0x0000000002852278>
如果在開發(fā)中,希望使用 print 輸出 對象變量 時,能夠打印 自定義的內(nèi)容,就可以利用 __str__ 這個內(nèi)置方法了
注意:
__str__方法必須返回一個字符串
class Cat:
def __init__(self, new_name):
self.name = new_name
print("%s 來了" % self.name)
def __str__(self):
return "我是小貓:%s" % self.name
tom = Cat("Tom")
print(tom)
Tom 來了
我是小貓:Tom
1.6 面向?qū)ο髒s面向過程
class Car:
def __init__(self,type,price):
self.type = type
self.price = price
self.distance = 0 #新車
def printCarInfo(self):
print ("the car's Info in class:type %s,price:%d"%(self.type,self.price))
def driveDistance(self,distance):
self.distance += distance
self.price -= distance*10
print(f'面向?qū)ο?)
carOne = Car('passat',250000)
carOne.printCarInfo()
carOne.driveDistance(100)
carOne.driveDistance(200)
print(f'passat已經(jīng)行駛了{carOne.distance}公里')
print(f'passat的價格是{carOne.price}')
輸出
面向?qū)ο?the car's Info in class:type passat,price:250000
passat已經(jīng)行駛了300公里
passat的價格是247000
小結(jié) 可以拿公司運營作為比喻來說明面向?qū)ο箝_發(fā)方式的優(yōu)點
外部調(diào)用代碼好比老板 面向過程中函數(shù)好比員工,讓員工完成一個任務(wù),需要老板不斷的干涉,大大影響了老板的工作效率。 面向?qū)ο笾袑ο蠛帽葐T工,讓員工完成一個任務(wù),老板只要下命令即可,員工可以獨擋一面,大大節(jié)省了老板的時間
還有一種說法
世界上本沒有類,代碼寫多了,也就有了類
面向?qū)ο箝_發(fā)方式是晚于面向過程方式出現(xiàn)的,幾十年前,面向?qū)ο筮€沒有出現(xiàn)以前,很多軟件系統(tǒng)的代碼量就已經(jīng)達到幾十上百萬行,科學(xué)家為了組織這些代碼,將各種關(guān)系密切的數(shù)據(jù),和相關(guān)的方法分門別類,放到一起管理,就形成了面向?qū)ο蟮拈_發(fā)思想和編程語言語法。