什么是對象
對象(Object)
既表示客觀世界問題空間中的某個具體事情仗岸,又表示軟件系統(tǒng)空間中的基本
元素
對象 = 屬性 + 方法
對象以id作為標(biāo)識戏锹,既包含數(shù)據(jù)(屬性)宋下,也包含代碼(方法)政模,是某一類具體事物的特殊實(shí)例笋熬。
對象是類的實(shí)例,是程序的基本單元
要創(chuàng)建一個新的對象菩鲜,首先必須定義一個類园细,用以指明該類型的對象所包含的內(nèi)容(屬性和方法)
同一類(class)的對象具有相同的屬性和方法,但屬性值和id不同接校。
對象名稱
賦值語句給予對象以名稱猛频,對象可以有對個名稱(變量引用),但只有一個id蛛勉。
例:a = complex(1, 2)
對象實(shí)現(xiàn)了屬性和方法的封裝鹿寻,是一種數(shù)據(jù)抽象機(jī)制
提高了軟件的重用性,靈活性诽凌,擴(kuò)展性
Python語言動態(tài)的特性毡熏,使得對象可以隨時增加或刪除屬性或方法
例: print(f.fx, f.fy)
f.fz = 3.4
print(f.fz)
del f.fz
面向?qū)ο缶幊?OOP)是一種程序設(shè)計(jì)范型,,同時也是皿淋、一種程序開發(fā)方法
程序中包含各種獨(dú)立而又能相互調(diào)用的對象招刹,每個對象都能接受恬试,處理數(shù)據(jù)并將數(shù)據(jù)傳遞給其他對象窝趣。
傳統(tǒng)程序設(shè)計(jì)
將程序看作一系列函數(shù)或指令的集合
類的定義與調(diào)用
什么是類
- 類(class)是對象的模板,封裝了對應(yīng)現(xiàn)實(shí)實(shí)體的性質(zhì)和行為
- 實(shí)例對象(Instance Object)是類的具體化
- 把類比作模具训柴,對象則是用模具制造出來的零件
- 類的出現(xiàn)為面向?qū)ο缶幊痰娜齻€最重要的特性提供了實(shí)現(xiàn)的手段(
封裝性
,繼承性
,多態(tài)性
)
類和函數(shù)相似哑舒,類是一系列代碼的封裝
Python中約定,類名用大寫字母開頭幻馁,函數(shù)用小寫字母開頭洗鸵,以便區(qū)分。
class語句:
class <類名>:
<一系列方法的調(diào)用>
類的初始化
class <類名>:
def __init__(self, <參數(shù)表>):
def <方法名>(self, <參數(shù)表>):
- _init_()是一個特殊的函數(shù)名仗嗦,用于根據(jù)類的定義創(chuàng)建實(shí)例對象膘滨,第一個參數(shù)必須是self
<類名>(<參數(shù)>)
調(diào)用類會創(chuàng)建一個對象,(注意括號~
)
obj = <類名>(<參數(shù)表>)
返回一個對象實(shí)例
類方法中的self指這個對象實(shí)現(xiàn)~
使用點(diǎn)(.)操作符來調(diào)用對象里的方法
class Force: # 力
def __init__(self, x, y): # x, y方向分量
self.fx = x
self.fy = y
def show(self): # 打印出力的值
print("Force<%s, %s>"%(self.fx, self.fy))
def add(selfl, force2):
x = self.fx + force2.fx
y = self.fy + force2.fy
return Force(x, y)
# 生成一個力對象
f1 = Force(0, 1)
f1.show()
# 生成另一個力的對象
f2 = Force(3, 4)
# 合成為新的力
f3 = f1.add(f2)
f3.show()
類定義中的特殊的方法
特殊方法(special method)
也被稱作魔術(shù)方法(magic method)
在類定義中實(shí)現(xiàn)一些特殊方法稀拐,可以方便的使用Python中一些內(nèi)置操作
所有特殊方法的名稱以兩個(__)開始和結(jié)束
對象構(gòu)造器 __init__(self, [...)實(shí)例化對象時調(diào)用
對象析構(gòu)器 __del__(self, [...)
from os.path import join
class FileObject:
'''給文件對象進(jìn)行包裝從而確認(rèn)在刪除是文件流被關(guān)閉 '''
def __init__(self, filepath=’~‘, filename='sample.txt'):
# 讀寫模式打開一個文件
self.file = open(join(filepath, filename), 'r+')
def __del__(self):
self.file.close()
del self.file
算術(shù)操作符
__add__(self, other): 使用+操作符
__sub__(self, other): 使用-操作符
__mul__(self, other): 使用*操作符
__div__(self, other): 使用/操作符
反運(yùn)算
當(dāng)左操作數(shù)不支持相應(yīng)的操作是被調(diào)用
__radd__(self, other)
__rsub__(self, other)
__rmul__(self, other)
__rdiv__(self, other)
大小比較
__eq__(self, other): 使用 == 操作符
__ne__(self, other): 使用 != 操作符
__lt__(self, other): 使用 < 操作符
__gt__(self, other): 使用 > 操作符
__le__(self, other): 使用 <= 操作符
__ge__(self, other): 使用 >= 操作符
例子:
class Force: # 力
def __init__(self, x, y): # x, y方向分量
self.fx = x
self.fy = y
def show(self): # 打印出力的值
print("Force<%s, %s>"%(self.fx, self.fy))
def add(selfl, force2):
x = self.fx + force2.fx
y = self.fy + force2.fy
return Force(x, y)
__add__ = add
def __str__(self):
return ”F<%s, %s>“%(self.fx, self.fy)
def __mul__(self):
x, y = self.fx * n, self.fy * n
return Force(x, y)
def __eq__(self, force2):
return (self.fx == force2.fx) and (self.fy == force2.fy)
# 操作符使用
f3 = f1 + f2
print("Fadd = %s"%(f3,))
f3 = f1 * 4.5
print("Fmul = %s"%(f3,))
print("%s == %s? ->%s"%(f1, f2, f1 == f2))
字符串操作
不僅數(shù)字類型可以使用+(__add__())和-(__sub__())的數(shù)學(xué)運(yùn)算符火邓,例如字符串類型可以使用+進(jìn)行拼接,使用*進(jìn)行復(fù)制
__str__(self): 自動轉(zhuǎn)換為字符串
__repr__(self): 返回一個用來表示對象的字符串
__len__(self): 返回元素個數(shù)
自定義對象的排序
列表排序 sort()
對原列表進(jìn)行排序,改變原列表內(nèi)容铲咨。
如果列表中的元素都是數(shù)字躲胳,默認(rèn)按升序排序
通過添加參數(shù)recerse=True可改變?yōu)榻敌蚺判?br>
如果元素都是字符串,則會按照字母表順序排序
>>> num = [4, 2, 7, 0,1]
>>> num.sort()
[0, 1, 2, 4, 7]
>>> num.sort(reverse = True)
>>> num
[7, 4, 2, 1, 0]
>>> name = ['John', 'Connor', 'Bruce', 'Arthur', 'Edward']
>>> name.sort()
>>> name
['Arthur', 'Bruce', 'Connor', 'Edward', 'John']
通用函數(shù) sorted()
類似sort()纤勒,但返回的是排好序的列表副本坯苹,原列表內(nèi)容不變
>>> name = ['John', 'Connor', 'Bruce', 'Arthur', 'Edward']
>>> sorted_name = sorted(name)
>>> sorted_name
['Arthur', 'Bruce', 'Connor', 'Edward', 'John']
>>> name
['John', 'Connor', 'Bruce', 'Arthur', 'Edward']
只有當(dāng)列表中的所有元素都是同一種類型的時候,sort()和sorted()才會正常工作
特殊方法 __lt__(less than)
由于Python的可擴(kuò)展性摇天,每種數(shù)據(jù)類型可以定義特殊方法
def __lt__(self, y)
返回True視為比y小粹湃,排在前
返回False視為比y大,排在后
只要類定義了特殊方法__lt__
泉坐,任何自定義類都可以使用 x < y
這樣比較再芋。
class Student:
def __init__(self, name, grade):
self.name = name, self.grade = grade
# 內(nèi)置sort()函數(shù)只引用 < 比較符來判斷前后
def __lt__(self, other):
# 成績比other高的,排在它前面
return self.grade > other.grade
# Student 的易讀字符串表示
def __str__(self):
return "Student(%s, %s)"%(self.name, self.grade)
# Student的正式字符串表示坚冀,我們讓它跟易讀表示相同
__repr__ = __str__
# 構(gòu)造一個列表济赎,加入Student對象
s = list()
# 添加Student對象到list中
s.append(Student("Jack", 80))
s.append(Student("Jane", 75))
s.append(Student("Smith", 82))
s.append(Student("Cook", 90))
s.append(Student("Tom", 70))
print("Original: ", s)
# 對list進(jìn)行排序,注意這里是內(nèi)置sort()方法
s.sort()
# 查看結(jié)果记某,已經(jīng)是按照成績排好序了
print("Sorted: ", s)
>>> Original: [("Jack", 80), ("Jane", 75), ("Smith", 82), ("Cook", 90), ("Tom", 70)]
>>> Sorted: [("Cook", 90), ("Smith", 82), ("Jack", 80), ("Jane", 75), ("Tom", 70)]
>>> s[0] < s[1]
True
直接調(diào)用列表sort方法司训,可以根據(jù) __lt__
定義排序。
直接檢驗(yàn) Student 對象的大小 s[i] < s[j]
另外可以定義其他比較符 __gt__
等(大于液南,小于壳猜,不等于···)
類的繼承
繼承(inheritance):如果一個類A繼承自另一個類B,就把A稱為子類滑凉,被繼承的B稱為父類(基類统扳,超類)
代碼復(fù)用:利用繼承可以從已有類中衍生出新的類,添加或修改部分功能畅姊。
新類具有舊類中的各種屬性和方法咒钟,而不需要進(jìn)行任何復(fù)制。
類的繼承機(jī)制
class Car:
def __init__(self, name):
self.name = name
self.remain_mille = 0
def fill_fuel(self, miles): # 加燃料里程
self.remain_mile = miles
def run(self, miles): # 跑miles英里
print(self.name, end=": ")
if self.remain_mile >= miles:
self.remain_mile -= miles
print("run %d miles!"%(miles,))
else:
print("fuel out!")
class GasCar(Car):
def fill_fuel(self, gas): # 加汽油gas升
self.remain_mile = gas *6.0 # 每升跑6英里
class ElecCar(Car):
def fill_fuel(self, power): # 充電power度
self.remain_mile = power * 3.0 # 每度電跑3英里
gcar = GasCar("BMW")
gcar.fill_fuel(50.0)
gcar.run(200.0)
>>> BMW: run 200 miles!
ecar = ElecCar("Tesla")
ecar.fill_fuel(60.0)
ecar.run(200.0)
>>> Tesla: fule out!
子類與父類
定義:如果兩個類具有“一般 -- 特殊”的邏輯關(guān)系若未,那么特殊類就可以作為一般類的“子類”來定義朱嘴,從“父類”繼承屬性的方法
class <子類名>(<父類名>):
def <重定義方法>(self, ...)
覆蓋(Override)
子類對象可以調(diào)用父類方法,除非這個方法在子類中重新定義了粗合。
如果子類同名方法覆蓋了父類的方法萍嬉,仍然還可以調(diào)用父類的方法。
子類還可以添加父類中沒有的方法和屬性
class GasCar(Car):
def __init__(self, name, capacity): # 名稱和排量
super().__init__(name) # 父類初始化方法隙疚,只有名稱
self.capacity = capacity
關(guān)于self
在類定義中壤追,所有方法的首個參數(shù)一般都是self
self的作用:在類內(nèi)部,實(shí)例化過程中傳入的所有數(shù)據(jù)都賦給這個變量供屉。
self實(shí)際上代表對象實(shí)例
<對象>.<方法>(<參數(shù)>) 等價(jià)于 <類>.<方法>(<對象>, <參數(shù)>)
gcar = GasCar("BMW")
gcar.fill_fuel(50.0)
gcar.fun(200.0) # 這里
GasCar.run(gcar, 200.0) # 和這里是等價(jià)的
異常處理
try-except語句
try:
<檢測語句>
except <錯誤類型> [as e]:
<異常處理>
try-finally語句
try:
<檢測語句>
except <錯誤類型> [as e]:
<異常處理>
finally:
<語句塊>
else語句
try:
<檢測語句>
except <錯誤類型> [as e]:
<異常處理>
else:
<語句塊>
else: # 沒有出錯執(zhí)行的代碼
例子
try:
print("try...")
r = 10 / 'xyz'
print("result: ", r)
except TypeError as e:
print("TypeError:", e)
except ZeroDivisionError as e:
print("ZeroDivisionError:", e)
else:
print("no error!")
finally:
print("finally...")
print("END")
>>>try...
TypeError: unsupported operand type(s) for /: 'int' and 'str'
finally...
END
推導(dǎo)式
什么是推導(dǎo)式
推導(dǎo)式是從一個或者多個迭代器快速簡潔地創(chuàng)建數(shù)據(jù)結(jié)構(gòu)的一種方法行冰。
將循環(huán)和條件判斷結(jié)合捅厂,從而避免語法冗長的代碼。
可以用來生列表资柔,字典和集合焙贷。
列表推導(dǎo)式
[<表達(dá)式> for <變量> in <可迭代對象> if <邏輯條件>]
[x**x for x in range(10)]
[x+y for x in range(10) for y in range(10)]
[x*x for x in range(10) if x % 2 == 0]
[x.upper() for x in [1, ‘a(chǎn)’, 'b', True] if isinstance(x, str)]
>>> ['A', 'B']
字典推導(dǎo)式
{<表達(dá)式>:<元素表達(dá)式> for <變量> in <可迭代對象> if <邏輯條件>}
{"k%s"%(x,):x**3 for x in range(10)}
集合推導(dǎo)式
{<元素表達(dá)式> for <變量> in <可迭代對象> if <邏輯條件>}
{x**3 for x in range(10)}
生成器推導(dǎo)式
返回一個生成器對象,也是可迭代對象贿堰。
但生成器并不會立即產(chǎn)生全部元素辙芍,僅在要用到元素的時候才會生成,可以極大節(jié)省內(nèi)存羹与。
(<元素表達(dá)式> for <變量> in <可迭代對象> if <邏輯條件>)
>>> agen = (x**x for x in range(3))
>>> agen
<generator object <genexpr> at 0x1078f5620>
>>> for i in agen:
print(i)
0
1
2
生成器函數(shù)
什么是生成器
生成器(generator)是用來創(chuàng)建數(shù)據(jù)序列的一種對象故硅。
使用它可以迭代龐大的序列,且不需要在內(nèi)存中創(chuàng)建和儲存整個序列纵搁、
通常生成器是為迭代器產(chǎn)生數(shù)據(jù)的吃衅。
如果要創(chuàng)建一個比較大的序列,生成器推導(dǎo)式將會比較復(fù)雜腾誉,一行表達(dá)式無法容納徘层,這是可以定義生成器函數(shù)。
生成器函數(shù)與普通函數(shù)
生成器函數(shù)的定義與普通函數(shù)相同利职,只是將return 換成 yield趣效。
yield 與 return
- yeild 語句
立即返回一個值
下一下迭代生成器函數(shù)時,從yeild語句后的語句繼續(xù)執(zhí)行猪贪,直到再次yield返回跷敬,或終止。 - return 語句
終止函數(shù)的執(zhí)行热押,下次調(diào)用會重新執(zhí)行函數(shù)西傀。
協(xié)同程序
可以運(yùn)行的獨(dú)立函數(shù)調(diào)用,函數(shù)可以暫屯把ⅲ或掛起拥褂,并在需要的時候從離開的地方繼續(xù)或重新開始。
def even_number(max):
n = 0
while n < max:
yield n
n += 2
for i in even_number(10):
print(i)
0
2
4
6
8