迭代器
迭代器介紹
迭代器指的是迭代取值的工具,迭代是指一個重復的過程,每一次重復都是基于上一
次結果而來迭代提供了一種通用的 不依賴索引 的迭代取值方式
可迭代對象
可以用 for 循環(huán)遍歷的對象都是可迭代對象房交。
- str,list,tuple,dict,set 等都是可迭代對象彻舰。
- generator (生成器 和 yield 的生成器函數) 也是可迭代對象。
判斷是否可迭代
# 查看是否有__iter__()方法來驗證其是否是一個可迭代對象
str() # 可迭代對象
list() # 可迭代對象
int() # 不可迭代
float() # 不可迭代
# 通過 isinstance 來判斷其是否是可迭代的對象
from collections import Iterable # collections是內置的模塊
print(isinstance('abc', Iterable)) # True
print(isinstance({1, 2, 3}, Iterable)) # True
print(isinstance(2.15, Iterable)) # Flase
迭代器
- 有內置的
__iter__()
方法的對象候味,執(zhí)行迭代器的__iter__()
方法得到的依然是迭代
器本身 - 有內置的
__next__()
方法的對象刃唤,執(zhí)行該方法可以不依賴索引取值
# 說明:可迭代的對象不一定是迭代器
# 1.看其是否含有__iter__以及__next__方法
# 2.看其是否屬于Iterator
from collections import Iterator
li = [1, 2, 3, 4]
print(isinstance(li, Iterator)) # False
iter()
可以被 next() 函數調用并不斷返回下一個值的對象稱為迭代器:Iterator 。那我們可
以通過 iter() 方法將可迭代的對象白群,轉為迭代器尚胞。
li = [1, 2, 3, 4]
print(type(li)) # <class 'list'>
li = li.__iter__()
lis = iter(li) # iter()方法就可以將可迭代的對象轉為迭代器
print(type(li)) # <class 'list_iterator'>
print(type(lis)) # <class 'list_iterator'>
li = [1, 2, 3, 4]
lis = iter(li)
# print(lis[0]) # 注意迭代器不能通過下表去取值
print(lis.__next__()) # 取 1
print(lis.__next__()) # 取 2
print(lis.__next__()) # 取 3
print(lis.__next__()) # 取 4
# print(lis.__next__()) # 超出長度,報錯;StopIteration
li = [1, 2, 3, 4]
lis = iter(li)
print(next(lis)) # 取 1
print(next(lis)) # 取 2
print(next(lis)) # 取 3
print(next(lis)) # 取 4
print(next(lis)) # 報錯 StopIteration
li = [1, 2, 3, 4]
lis = iter(li)
for i in lis:
print(i)
while True:
print(lis.__next__()) # 報錯 StopIteration
注意:
- 迭代器不可以通過下標取值帜慢,而是使用
__next__()
或者 next() 笼裳。但是只要超出
范圍則直接報錯 StopIteration 唯卖。 - next() 只能順延調用,不能往前躬柬。
可迭代對象與迭代器區(qū)別
- 可用于 for 循環(huán)的都是可迭代類型
- 作用于 next() 都是迭代器類型
- list 拜轨、 dict 、 str 等都是可迭代的但不是迭代器,因為 next() 函數無法調用它們允青¢夏耄可
以通過 iter() 函數將它們轉為迭代器 - python 的 for 循環(huán)本質就是通過不斷調用 next() 函數實現(xiàn)的
生成器
生成器定義
在 Python 中,一邊循環(huán)一邊計算的機制颠锉,稱為生成器:generator法牲。
那么生成器就是在循環(huán)的過程中根據算法不斷推算出后續(xù)的元素,這樣就不用創(chuàng)建整個完整的列表琼掠,
從而節(jié)省大量的空間皆串。
如何創(chuàng)建生成器
生成器表達式
生成器表達式來源于 迭代 和 列表解析 的 組合,生成器和列表解析類似眉枕,但是它使用 () 而不是 []。
g = (i for i in range(5))
# print(g) # generator
# print(g[0]) # 生成器不可通過下表取值
print(next(g)) # 取 0
print(next(g)) # 取 1
print(next(g)) # 取 2
print(next(g)) # 取 3
print(next(g)) # 取 4
print(next(g)) # 生成器也是可迭代的對象怜森,超出長度則報錯: StopIteration
g = (i for i in range(5))
for i in g:
if i < 3:
print(i)
如何創(chuàng)建生成器
生成器函數
實現(xiàn) :
- 生成一個自定義長度的列表
需求: - 定義函數 yieldtest
- 通過函數參數指定列表長度
# 在函數中加入yield,該函數就變?yōu)樯善骱瘮?def yield_test(number):
n = 0
li = []
while n < number:
li.append(n)
yield n
n += 1
print(li)
res = yield_test(20)
# print(res) # generator
print(next(res)) # 取 0
print(next(res)) # 取 1
print(next(res)) # 取 2
print(next(res)) # 取 3
print(next(res)) # 取 4
print(next(res)) # 取 5 ////////. 6y5
如何創(chuàng)建生成器
生成器函數( yield )
當一個函數中包含 yield 關鍵字速挑,那么這個函數就不再是一個普通的函數,而是一個 generator 副硅。
調用函數就是創(chuàng)建了一個生成器對象姥宝。其工作原理就是通過重復調用 next() 或者 __next__()
方法,
直到捕獲一個異常恐疲。
如何創(chuàng)建生成器
生成器函數( yield )
注意:
yield 返回一個值腊满,并且記住這個返回值的位置,
下次遇到 next() 調用時培己,代碼從yield 的下一條語
句開始執(zhí)行碳蛋。與 return 的差別是,return 也是返回
一個值省咨,但是直接結束函數肃弟。
# 斐波那契數列:除了第一個與第二個以外,任何一個數都可以由前兩個相加得到零蓉。
def createNums():
print("----func start----")
a, b = 0 , 1
for i in range(5):
# print (b)
print('--1--')
yield b
print('--2--')
a, b = b, a+b
print('--3--')
print('----func end----')
g = createNums()
print(next(g)) # 打印--1-- 1笤受,veild將b給返回,返回給next(g)
print(next(g)) # 遇到第二個next(g),會接著下一次yeild下面的代碼繼續(xù)執(zhí)行
print(next(g))
# return:函數的返回值敌蜂,當函數代碼執(zhí)行到return時箩兽,就退出函數,也就是說return下面的代碼都不會再執(zhí)行章喉。
# yield:是將函數變?yōu)樯善麝P鍵字汗贫,將值返回到next(g)身坐,只不過再遇到下一個next(g)的時候,會接著上一次執(zhí)行的代碼繼續(xù)執(zhí)行芳绩。
for i in g:
print(i)
生成器函數( yield )
send() 和 next() 一樣掀亥,都能讓生成器繼續(xù)往下走一步(遇到 yield 返回),但 send() 能傳一個值妥色,
這個值作為 yield 表達式整體的結果搪花。
生成器函數( yield )
思考 : 右邊代碼輸出
hello ?
world ?
hello world ?
# send講解
def test():
# 1.賦值運算符從右到左
a1 = yield'hello' # 2.a = "world"
# 3.將a1返回到send處了
yield a1
res = test()
# print(next(res)) # hello
# print(res.send('world')) # world
# print(res.send('world')) # 注意:如果yield已經返回完,那在使用next或者send的時候就會報錯
# print(res.send('hello')) # 非空的值不能作為啟動生成器的對象
print(res.send(None)) # 相當與next()
迭代器與生成器
- 生成器能做到迭代器能做的所有事
- 因為生成器自動創(chuàng)建了 iter() 和 next() 方法嘹害,生成器顯得簡潔撮竿,而且高效。
面向對象編程
面向對象編程介紹
面向對象編程: Object Oriented Programming笔呀,簡稱OOP幢踏,是一種程序設計思想。
需要注意的是许师,與之對應的是面向過程編程思想房蝉。實際上,能夠使用面向對象編程思想實現(xiàn)的程序微渠,
也都能通過面向過程完成搭幻。只是看哪種思想更適合當前開發(fā)需求。
面向過程與面向對象區(qū)別:
- 面向過程:根據業(yè)務邏輯從上到下寫代碼
- 面向對象:將數據與函數綁定到一起逞盆,進行封裝檀蹋。減少重復代碼的重寫過程
面向對象概念及術語
類
類是抽象的概念,僅僅是模板云芦。用來描述具有相同屬性和方法的對象的集合俯逾。
比如:"人"是一個類。
對象
某一個具體事物的存在 ,在現(xiàn)實世界中可以是看得見摸得著的舅逸。 比如:"胡歌
"就是一個對象桌肴。
類與對象的關系
那么實際上,我們可以進行對象歸類琉历。
類與對象的關系
小練習: 下面哪些是類识脆,哪些是對象?
類的構成
類由3個部分構成
- 類的名稱:類名
- 類的屬性:一組數據
- 類的方法:允許對類進行操作的方法
類的定義
Python 使用 class 關鍵字來定義類善已,其基本結構如下:
注意: 類名通常采用駝峰式命名方式灼捂,盡量讓字面意思體現(xiàn)出類的作用。
創(chuàng)建對象
python 中换团,可以根據已經定義的類去創(chuàng)建出一個個對象
小練習
- 創(chuàng)建類:學生類
- 創(chuàng)建對象:張三
- 在類中定義方法輸出:張三學習Python
class LogicStudents:
def study_python(self):
print('張三學python')
LogicStudents() # 創(chuàng)建對象
zs = LogicStudents() # 將對象賦值給zs悉稠,也可以理解未創(chuàng)建了zs這個對象(實例)。實例化的過程
zs.study_python() # 通過 對象 方法名()調用類中的方法
self 參數
在類當中定義方法時艘包,會發(fā)現(xiàn)系統(tǒng)幫我們自動創(chuàng)建了self 參數的猛,并且在調用
對象的該方法時耀盗,也無需傳入 self
參數。那這個 self
是什么卦尊?
實際上叛拷,我們需要明確 self
的兩個概念
- self 本身是
形參
- self 就是
對象本身
小練習
ü 定義類為:學生類
ü 創(chuàng)建對象:李四
ü 在類中定義方法:打印李四信息
class LogicStudent:
def test_one(self):
print(self)
# self就是對想本身,也就是說岂却,當創(chuàng)建的對象是誰時忿薇,self就是誰
N_stu = LogicStudent()
# 體現(xiàn)了 self 與N_stu 是同一個對象
print(N_stu) # <__main__.LogicStudent object at 0x012CC330>
N_stu.test_one() # <__main__.LogicStudent object at 0x012CC330>
xia_gu = LogicStudent()
# 體現(xiàn)了 self 與 xia_gu 是同一個對象
print(xia_gu) # <__main__.LogicStudent object at 0x018D2190>
xia_gu.test_one() # <__main__.LogicStudent object at 0x018D2190>
class LogicStudent:
def stu_infor(self):
# print(N_stu.name, N_stu.age)
# print(xia_gu.namem xioa_gu.age)
print(self.name, self. age)
# 思考:在類當中是否可以訪問到對象自己屬性。是可以的
N_stu = LogicStudent()
N_stu.name = 'N'
N_stu.age = 18
N_stu.stu_infor()
xia_gu = LogicStudent()
xia_gu.name = "xia_gu"
xia_gu.age = 19
xia_gu.stu_infor()
init() 方法
__init__()
方法稱為 初始化方法
躏哩,也可稱為構造方法署浩。在創(chuàng)建對象時,會自動
執(zhí)行該方法扫尺,為對象的屬性設置初始值筋栋。
猜一猜,以下代碼會先輸出--1--,還是先輸出--2-- 正驻?
class Student():
def __init__(self):
print('--1--') # 1
s = Student() # 初始化方法弊攘,他在創(chuàng)建對象后自動執(zhí)行的方法
print('--2--') # 2
class LogicStudent:
def __init__(self, sut_name, sut_age): # __init__方法 形參
# 初始化對象的屬性
# self.name = 'N'
# self.age = 18
self.name = sut_name
self.age = sut_age
def sut_infor(self):
print(self.name, self.age)
N_sut = LogicStudent('N', 18) # __init__方法 實參傳遞
N_sut.sut_infor()
M_miao = LogicStudent('miao', 28)
M_miao.sut_infor()
class LogicStudent:
def __init__(self, stu_name, stu_age): # __init__方法 形參傳遞
self.name = stu_name
self.age = stu_age
# 1.__init__方法是否可以由返回值:可以,但是必須為None
# retrun "111" # __init__() should return None, not 'str'
def stu_infor(self):
# print(self.name, self.age)
self.gender = 'female'
self.addr = 'ChangSha'
N_stu = LogicStudent('N', 18) # __init__方法 實參傳遞
# 2.在__init__方法中聲明的屬性姑曙,可否在類的外部通過對象訪問襟交?可以
# print(N_stu.name, N_stu.age)
# 3.在自定義的方法當中定義對象的屬性,注意需要需要先調用指定的方法渣磷,才會將gender屬性以及addr屬性封裝到該對象中才可以訪問
N_stu.stu_infor()
print(N_stu.gender)
print(N_stu.addr)
str() 方法
如果在開發(fā)中,希望打印輸出對象變量時授瘦,能夠打印自定義的內容醋界。就可以
使用 __str__()
方法,將自定義內容通過return
關鍵字返回提完。
注意:返回值必須是字符串
class LogicStudent:
def __init__(self):
pass
s = LogicStudent()
print(s) # 實例所在的內存地址 <__main__.LogicStudent object at 0x012CC390>
class LogicStudent:
def __init__(self):
self.name = 'N'
self.age = 18
def __str__(self):
# return self.name # "N"
# return self.age # 報錯形纺,注意:__str__方法必須返回的是字符串
# return self.name, self.age # 因為return返回多個時會打包成元組隨意此處報錯
return f'{self.name},{self.age}'
s = LogicStudent()
print(s) # N,18