python进阶教程day_python从零进阶之路——day4
高階函數
函數在內存中存儲方式跟變量一樣,計算機會為函數開辟內存空間存放函數體,同時函數名指向這個內存空間,函數名相當于句柄(內存地址),函數可以賦值給變量,通過變量調用,函數與變量一樣也可以作為參數傳給另一個函數。
把函數作為參數傳入,這樣的函數稱為高階函數,函數式編程就是指這種高度抽象的編程范式。
#author:zingerman
defadd(x,y,func):print(func(x)+func(y))
add(2,-3,abs)#abs是絕對值函數的句柄,指向內存中的函數體,func==abs , func()==abs()
高階函數之map函數
#map()函數接收兩個參數,一個是函數,一個是Iterable#map將傳入的函數依次作用到序列的每個元素,并把結果作為新的Iterator返回。
deff(x):return x*x
r=map(f,[1,2,3,4]) #返回結果的內存地址
print(list(r)) #[1, 4, 9, 16]
也可以這樣:
deff(x,y):return x*y
r=map(f,[1,2,3,4],[1,2,3,4]) #返回結果的內存地址
print(list(r)) #[1, 4, 9, 16]
一段代碼將裂變轉化成字符串
高階函數之reduce函數
reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
#author:zingerman
from functools importreduce #結果24,相當于sum 函數deff (x,y):return x*yprint(reduce(f,[1,2,3,4]))
from functools importreducedeff (x,y):return x*10+yprint(reduce(f,[1,2,3,4])) #將[1,2,3,4]轉換成1234
deffunc(x,y):return x*10+ydefchar2num(s):
digter={'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}returndigter[s]print(list(map(char2num,'12345'))) #[1, 2, 3, 4, 5]
print(reduce(func,map(char2num,'12345'))) #12345 相當與int()函數
from functools importreduce#簡化版str2int函數
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}defchar2num(s):returnDIGITS[s]defstr2int(s):return reduce(lambda x, y: x * 10 + y, map(char2num, s))
高階函數之filter函數
filter()把傳入的函數依次作用于每個元素,然后根據返回值是True還是False決定保留還是丟棄該元素。
#author:zingerman#使用filter判斷是不是奇數,并保留
defis_odd(n):return n%2==1
print(list(filter(is_odd,[1,2,3,4,5,6])))#[1, 3, 5]
filter()函數返回的是一個Iterator,也就是一個惰性序列,所以要強迫filter()完成計算結果,需要用list()函數獲得所有結果并返回list
裝飾器(Decorator)? ? ? 高階函數+嵌套函數==》》裝飾器
本質:一個返回函數的高階函數
作用:為其他函數添加附加功能
原則:1.不能修改被裝飾函數的源代碼
2.不能修改被裝飾函數的調用方式
實現裝飾器的知識儲備:
1.函數即"變量"
2.高階函數
3.嵌套函數
#author:zingerman
importtimedefdeco(func):
start_time=time.time()
func()
end_time=time.time()print('花費的時間%s'%(end_time-start_time))deftest():
time.sleep(1)print('in the test')
deco(test)#將test賦值給func,增加了功能,沒有改變test的源代碼,但是改變了函數的原本調用方式test()
#author:zingerman
importtimedef deco2(func):#deco2(test) func=test deco2函數的目的就是定義deco1函數,并拿到deco1的內存地址
defdeco1():
start_time=time.time()
func()
end_time=time.time()print('花費的時間%s'%(end_time-start_time))returndeco1deftest():
time.sleep(1)print('in the test')
test=deco2(test) #想要以test()這種調用方式實現附加功能而不改變test源代碼,
test() #只有把deco1賦值給test,然后test()執行,現在的test是加了新功能的deco1
#所以將deco1嵌套入deco2函數,并返回deco1,這樣就拿到了deco1的內存地址
#author:zingerman
importtimedef deco2(func):#deco2(test) func=test deco2函數的目的就是定義deco1函數,并拿到deco1的內存地址
defdeco1():
start_time=time.time()
func()
end_time=time.time()print('花費的時間%s'%(end_time-start_time))returndeco1
@deco2#相當于test=deco2(test)
deftest():
time.sleep(1)print('in the test')
test()
#author:zingerman
import time #帶參數的裝飾器
defdeco2(func):def deco1(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs)
end_time=time.time()print('花費的時間%s'%(end_time-start_time))returndeco1
@deco2#相當于test=deco2(test)
deftest(x):
time.sleep(1)print(x)print('in the test')
test(2)
生成器:
python使用生成器對延遲操作提供支持,延遲操作就是在有需要的地方產生結果,而不是立即產生結果
python有兩種方法提供生成器:
1.生成器函數:常規函數定義,但是使用yield而不是return返回結果,yield語句每次返回一個結果,之后掛起函數的狀態,以便下次從yiled之后開始執行,相當于在yield處產生了一個中斷
#author:zingerman
def fib (n): #用生成器產生斐波那契數列
a, b = 0, 1
for i inrange(n):yield(b)
a,b=b,a+b#=fib(10)
for i in fib(10):print(i)
2.生成器表達式:類似于列表推導,但是生成器一次產生一個結果,而不是一次就產生一個列表,儲存所有結果。(x**2 for x in range(5))
python中的很多內置函數都是用了迭代器協議去訪問對象,而生成器實現了迭代器對象,如for函數,sum函數
>>> sum(x ** 2 for x in xrange(4))
而不必這樣寫>>> sum([x ** 2 for x in xrange(4)])
#author:zingerman
importtimedefconsume(name):print('%s準備吃包子了'%name)whileTrue:
baizi=yield
print('%s包子來了,被%s吃了'%(baizi,name))#f=consume('hulida')#f.__next__()#f.send('韭菜餡')
defproducer(name):
c1= consume('A')
c2= consume('B')
c1.__next__()
c2.__next__()print("老子開始準備做包子啦!")for i in range(10):
time.sleep(1)print("做了1個包子,分兩半!")
c1.send(i)
c2.send(i)
producer('hu')
迭代器:
我們已經知道,可以直接作用于for循環的數據類型有以下幾種:
一類是集合數據類型,如list、tuple、dict、set、str等;
一類是generator,包括生成器和帶yield的generator function。
這些可以直接作用于for循環的對象統稱為可迭代對象:Iterable。
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator
可以使用isinstance()判斷一個對象是否是Iterable或Iterator對象:
集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象
from collections importIterable>>>isinstance([], Iterable)
True>>>isinstance({}, Iterable)
True>>> isinstance('abc', Iterable)
True>>> isinstance((x for x in range(10)), Iterable)
True>>> isinstance(100, Iterable)
False
>>> from collections importIterator>>> isinstance((x for x in range(10)), Iterator)
True>>>isinstance([], Iterator)
False>>>isinstance({}, Iterator)
False>>> isinstance('abc', Iterator)
False
總結
以上是生活随笔為你收集整理的python进阶教程day_python从零进阶之路——day4的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 李洋疯狂C语言之n个人报数,报到3的退出
- 下一篇: STL之map和multimap容器