今天換了師傅。江湖人稱景女神^o^。 女師傅講的比較細,原理的比較多。初學者來說有些難。但是基本功是必須要打牢的。努力!
迭代器
迭代器,迭代的工具
1 什么是迭代,指的是一個重復的過程,每一次重復稱為一次迭代,并且每一次重復的結果是下一次重復的初始值
while True:
print("=====")
l = ["a","b","c",]
count = 0
while count < len(l):
count +=1
2 為什么要有迭代器?
對序列類型:str list tuple可以用索引取值,
但是對非序列類型,如元祖,set 文件內容,python必須為我們提供一種不依賴于索引的迭代取值的方式--->迭代器
dic = {"name":"jack","age":18,"hobbie":"readbook"}
3 可迭代對象:
有obj.__iter__ 這個方法的對象 就是可迭代對象
可迭代對象需要有多個值 有六種
str
list
tuplt
dict
set
file
可以使用__iter__方法 看一下是否是可迭代對象
如:str.__iter__
4 迭代器對象
file 文件類型是迭代器對象,只有滿足__iter__方法,同時還要有__next__方法
總結:
1,可迭代對象不一定是迭代器對象
2,迭代器對象一定是可迭代的對象
3,調用obj.__iter__()方法,可以把可迭代對象變為迭代器對象
4,對于迭代器對象,執行__iter__方法得到的還是他本身 還是迭代器對象
變為迭代器對象后 就可以迭代取值了
d={"user":"jack","age":18,"sex":"man"}
d_iter = d.__iter__()
print(d_iter.__next__())
還可以寫成這樣:
d = {"a","b","c"}
d_iter = iter(d)
print(next(d_iter))
# for循環詳解:
1,調用in后的l_iter = l.__iter__()
2,i = l_iter.__next__()
3,捕捉StopIteration異常,結束迭代。
l = ["a","b","c"]:
for i in l :
print(i)
總結迭代器的 優缺點:
優點:1 提供一種統一的,不依賴索引的取值方法
為for循環的實現提供了依據
2 迭代器同一時間在內存中只有一個值 --->更節省內存
缺點: 1 只能往后走,并且循環一遍就結束了。
2 不能統計值得個數,即長度
def eater(name):
print("%s ready to eat"%name)
while True:
food=yield
print("%s start to eat %s" %(name,food))
這種表達式需要先初始化才能執行
1 生成迭代器
e = eater("n=jack")
2 初始化:
e.send("None")
3 傳值:
e.send("吃屎")
同時這個表達式還可以組合使用
food = yield food_list
這個food_list就是返回值。print可以得到這個值
生成器
生成器: generater
自己寫的迭代器,就是一個生成器
py提供了兩種自己寫生成器(迭代器)的機制,生成器函數,生成器表達式
1 生成器函數:
yield
凡是帶生成器關鍵字的就是生成器
生成器函數調用不會觸發代碼的執行,而是會返回一個生成器(迭代器)
想要執行需要使用過next來進行調用
def func():
print("aaaaa")
yield 1
print("bbbbbb")
yield 2
記錄當前所在位置,等待下一次next來出發函數的調用
列子:
使用生成器監聽文件輸入的列子
####### 注意這個例子需要ctrl + s 保存一下輸入的文件 才能顯示監聽文件輸入的內容
####### mac系統需要寫個python程序來往文件中輸入,才能顯示
import time
def listion_file():
with open("userinfo") as f:
while True:
line = f.readline()
if line:
yield print(line.strip()):
time.sleep(0.1)
g = listion_file
for i in g:
print(i)
關鍵字:send
定義,在執行next的過程中,傳遞一個參數給生成器函數的內部
def foo():
print(1111)
res1 = yield 1
print(22222,"res1:",res1)
res2 = yield 2
print(33333,"res2:",res2)
yield 3
g = foo()
res = next(g)
print(res)
g.send("alex")
g.send("jack")
從函數的外部向內部傳參,但是在生成器第一次中不能send傳值,需要先激活next一下。
例子
計算移動平均值:
月度的天平均收入
def argvs():
day = 0
sum_moeny = 0
while True:
moeny = yield avg
sum_moeny +=money
day +=1
avg = sum_moeny/day
g = argvs()
next(g)
g.send(200)
g.send(400)
### 預激生成器
每個生成器都需要next預激活,如果有多個生成器,就比較麻煩
可以寫個裝飾器來進行預激活,這個裝飾器就叫預激生成器
### yield from
一般寫法:
def generator_func():
for i in range():
print(i)
for o in "hello"
print(o)
可以寫成:
def generator_func():
yield from range(5)
yield from "hello"
取值的方法:
1 next(g) 隨時可以停止,最后一次會報錯
2 for i in g:
print(g) 從頭到尾遍歷一次,不遇到break return不會停止
3 list 或 tuple 吧值放入列表或元祖,但是占用內存大。
print(list(g))
注意: 生成器不能直接next(生成器函數),必須要先生成生成器 然后在next使用
錯誤的:
print(next(func()))
正確的:
g = func()
print(next(g))
生成器特點: 節省內存,惰性計算,解決內存問題,和程序功能之間的解耦
總結:
1,yield 為我們提供了一種自定義迭代器對象的方法
2,yield 可以返回多個值 return 只能返回一次值
3,函數暫停與在繼續的狀態是yield幫我們保存的
三元表達式
def my_max(x,y):
x if x > y else y
在比如
name = inpurt("請輸入您的名字:")
res = "SB" if name == "alex" else "NB"
print(res)
if右邊是條件為真時返回的值,else左邊就是為假返回的值。
列表生成器,生成器表達式
列表推到式 數據小的時候可以使用這個。
ll = [i**2 for i in range(10)]
print(ll)
直接把循環得到的i在for右邊進行運算,得到的全部結果賦值給ll
生成器表達式 在數據龐大的時候 建議使用生成器表達式
gg = (i for i in range(10))
for i in gg:
print(i)
總結: 1 一個生成器 只能取一次,
2 生成器在不找他要值得時候,始終不執行
3 當他執行的時候,要以執行時候的所有變量值為準
兩者主要區別是列表推到式用中括號括起來,生成器是用小括號括起來。
練習:
取出文件中最長行數:
with open("test.txt","r",encoding="utf-8") as f:
g = (len(line) for line in f)
print(max(x))
上面兩行可以精簡為一行
print(max(len(line) for line in f))
sum求和
print(sun(len(line) for line in f))
文件每一行的字符個數
遞歸
定義: 在調用一個函數的過程中,直接或者間接有調用該函數本身,稱之為遞歸調用
遞歸必備的兩個階段:
1.遞推
2.回朔
def func():
print("--->")
func()
func()
這個遞歸是死循環
最多就到1000層 python就不允許遞歸了
import sys
print(sys.getrecursionlimit)
sys.setrecursionlimit(2000)
這樣可以修改最大允許遞歸多少層
下面的也是遞歸調用:
def func()
print("from func")
bar()
def bar():
print("from bar")
func()
bar()
遞歸的列子 先遞推, 然后在回溯
def age(n)
if n == 1
return 18
return age(n-1) +2
res =age(5)
print(res)
這個就是n等于5 先逐層往下遞推,滿足n 等于1就返回age(1)等于18 然后回朔 age(2)等于20
最后結果就是26
遞歸列表的值
l = ["a","b","c","d","e",[1,2,3,4,["b","h","j"]]]
def func(l):
for item in l:
if type(item) is list:
func(item)
else:
print(item)
匿名函數
lambda 表達式
def add(a,b):
return a+b
可以寫為:
add = lambda a,b: a+b
print(add(1,2))
求平方的方法可以寫一行
for i in map(lambfa num : num**2,range(10)):print(i)
練習:
print(min(-2,3,-4,key=lambad num:num%2))
內置函數
內置函數
print()
len()
abs()
max()
min()
eval()
zip()
dir()
總共有68個
反射相關 2
基礎數據類型相關 38
作用域相關 2
locals 本地命名空間
globals 全局命名空間
面向對象相關 9
迭代器/生成器 3
range
next
iter
其他函數 12
inpurt
print
可以指定分隔符 sep=";" 還可以去掉結尾換行符,end="" 不是每執行一個for循環就打印,加上Flush=True 就會實時打印
其實print實際上是寫文件。需要發起系統調用才能操作文件,如果print與print之間間隔較快,print會先先緩存一下在打印出來
加上flush=True就不會等待了。
如果在字符串中加上\r 就會一直在第一行覆蓋打印 相當于seek(0)
練習題:
進度條
hash
對可hash得數據類型進行hash之后會得到一個數字
在一次執行程序的執行過程中,對相同的可hash變量,哈希之后的結果幾乎總是是不相同的。
hash 字典底層的存儲,和set集合的去重機制都相關
print(hash("123456"))
print(hash("123456"))
id
查看一個變量的內存地址
import
引用模塊
help
查看幫助信息比如這個變量怎么用,這個對象怎么用等
callable
查看是否可調用
def foo():pass
a = 1
callable(a) 返回Flose
callable(foo) 返回True
dir
查看一個變量所擁有的所有名字,不止方法。
print(dir("1"))
數據類型類:
bool
bin
轉換為二進制 0b
oct
轉換為8進制 0o
hex
轉換為16進制 0x
abs
計算數字的絕對值,只能接收數字
divmod()
商余函數
print(divmod(10,2))
print(divmod(7,3))
print(divmod(9,7))
返回一個元祖,里面有兩個值,一個是商幾后一個是余幾
round
精確到小數點幾位,精確的幾位。四舍五入
print(round(3.1415926,4))
pow
求平方, 可以放第三個參數,第三個參數就是取余
print(pow(2,3))
print(pow(3,2,2))
sum
求和 接收一個可迭代對象,后面可以寫一個起始值 默認起始值是從0開始計算。
print(sum([1,2,3,4,5],20))
可以放入一個生成器(迭代器),這樣可以節省內存。
print(sum(range(1,6)))
min
取最小值
print(ming(1,-2,3,-4,key=abs))
當兩個最小值時取第一個
max
取最大值
序列
reversed
取反 只能傳入一個序列的數據結構,新生成一個迭代器,返回值取反,同時不改變原本的數據順序
reversed(ret)
用處:可以吧元祖reversed 然后在list這個元祖 可以都得到一個反轉的元祖。
format
格式化輸出,可以居中顯示
format("text" <20) <20 ^20
bytes
字符串轉bytes
ord
print(ord("a")) 小寫的a-z從 97開始 + 26,大寫的A-Z從65+26
轉換為acsii對應的數字
chr
print(chr(97))
轉換為acsii對應的字母
ascii
字符串轉ascii碼
repr
可以讓一個數據的數據類型可以原形畢露
a = 1
b = "1"
rper(a)
rper(b)
len
統計長度
enumerate
接收一個容器類型,一般是元祖或列表,可以制定下標起始值
list1 = ["香蕉","蘋果"]
for k,v in enumerate(list1,1)
print(k,v)
all
接收容器
判斷數據類型是否存在False,如果存在就都為Flase
any
接收容器
判斷數據類型中是否存在True類型,如果存在就都為True
zip
ret = zip([1,2,3,4],("a","b","c","d"),(4,5,6,7)) #拉鏈方法
返回一個可迭代函數
for i in ret:
print(i)
filter
可以吧列表(可迭代數據類型),逐個傳入函數當作參數,進行操作。
list1 = [1,2,4,6,9,11,17]
def func(num)
if num %2 == 0:reture num
for i in filter(func,list1)
print(i)
去除空字符
ll = ['test', None, '', 'str', ' ', 'END']
def func(strs):
if strs and strs.strip():return True 如果是True就返回
for i in filter(func,ll)
print(i)
map
range(10) 求他的平方:
推到式簡單;i**2 for i in range(10)
用map
def func(num):
return num **2
for i in map(func,range(10)):print(i)
就是把函數放到map里面去執行
sorted
先說一下key: 可以指定按abs絕對值, 可以指定len 等內置函數,來根據函數返回值來進行運算
l = [1,2,-3,-4,4,5,6]
l.sort(key=abs)
print(l)
使用sorted
new_l = sorted(l,key=abs)
print(new_l)
這個有些例外,直接返回值。
執行內置函數:
eval 執行字符串中的代碼 同時有返回值,吧結果返回。 注意這個函數有安全風險! 傳入惡意程序會執行。
eval(print("123"))
exec 執行字符串中的代碼,但是沒有返回值
exec(print("123"))
注意: min max sorted filter map 面試容易問到