1. 程式人生 > >python學習之路-day4.1

python學習之路-day4.1

函數(高階函數、嵌套函數、匿名函數) 裝飾器 生成器


裝飾器需要了解以下三點知識:

1、函數即變量;

2、高階函數;

3、嵌套函數;

所以首先先普及一下知識點:

變量定義x = 1,數據1讀取到內存中,可以理解為存到一房間中,而x表示房間號;

函數定義,函數體部分讀取到內存中,而函數名表示房間號;

def test():

print("in the test func")

所以本質上函數即變量

函數

  • 匿名函數

匿名函數關鍵字lambda,一般的函數定義為def foo():會定義名字,匿名函數表示方式:

calc = lambda x:x*3

calc(3) 調用方式

  • 高階函數

高階函數:把一個函數名當作實參傳給另外一個函數或者返回值中包含函數名的函數就是高階函數。

import time

def bar():

time.sleep(2)

print("inthebar")

def test(func):

start_time=time.time()

func()

stop_time=time.time()

print("thefuncruntimeis%s"%(stop_time-start_time))

test(bar)

此函數符合第一條規則,故為高階函數。此程序目的是不改變bar函數源代碼的情況下,增加了新功能,但改變了bar的調用方式。

def bar():

time.sleep(1)

print("inthebar"

)

def test(func):

print(time.localtime())

returnfunc


bar=test(bar)

bar()

此函數符合第二條規則,故也為高階函數。此程序的目的是不改變bar的調用方式。



  • 嵌套函數

嵌套函數是在一個函數中再定義一個函數

def foo():

print("inthefoo")

def bar():

print("inthebar")

bar()

foo()

即在一個函數體中,有關鍵字def定義另外一個函數。


裝飾器

本質是函數,用來裝飾其它函數。當某個項目中已經上線運行,有新需求需要對某些函數添加新功能,此時需要用到裝飾器。


裝飾器優勢:

1、不需要修改被裝飾函數的源代碼;

2、不需求改變被修飾函數的調用方式;


裝飾器示例:

import time

def timer(func):

def warpper(*args,**kwargs):

start_time=time.time()

func()

stop_time=time.time()

print("the func run time is %s" %(stop_time-start_time))

return warpper

@timer

def test():

time.sleep(2)

print("inthetest")

test()

裝飾器為嵌套函數,註意必須有返回值否則報TypeError: 'NoneType' object is not callable的錯誤

@timer其實相當於test=timer(test),註意調用位置不同,test=timer(test)需在函數test之後調用


生成器



列表生成式:使代碼更簡潔

>>> a=[ i*2 for i in range(10)]

>>> a

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

更負責的列表生成式:在i*2的位置可以更替為函數func(i)


簡單的生成器:

>>> a=( i*2 for i in range(10))

只是把[]變為(),此時a就是一個生成器,生成器只是存儲了一個算法邏輯,數據只有在用到的時候才生成。當數據量很大時可以明顯感覺到列表生成式耗時大,此時就需要用到生成器。

優點:節省內存

缺點:

1、只記錄當前位置,並只有一個__next__()方法;

2、可以使用for循環依次生成訪問;

3、只能一個一個訪問,且不能回溯,訪問數據不方便;


函數生成器,使用關鍵字yield,如程序:

def fib(max):

a,b=0,1

for i in range(max):

c=a+b

a=b

b=c

yield a

return done #return的值是異常時返回的內容

f=fib(4)

print(f.__next__())

print(f.__next__())

print(f.__next__())

print(f.__next__())

print(f.__next__())

如果使用__next__()方法調用,一旦超過數據長度,就會產生一個異常:

File "D:/PycharmProjects/untitled/20180409/斐波那契.py", line 32, in <module>

print(f.__next__())

StopIteration

可以使用以下程序替換f.__next__(),其中try捕捉報錯類型並提示以優化程序:

while True:

try:

x=next(f)

print('f:',x)

except StopIteration as e:

print("Generatorreturnvalue:",e.value)

break


生成器應用實例:

import time

def costumer(name):

print("%s要吃包子了"%(name))

while True:

baozi=yield

print("%s包子來了,請%s來吃包子吧!"%(baozi,name))

return"沒有包子了"

def producer(baozi_list):

client1=costumer("劉翔")

client2=costumer("田立三")

client1.__next__()

client2.__next__()

for i in baozi_list:

print("\033[1;31m正在做包子\033[0m")

time.sleep(3)

print("%s包子做好了"%(i))

client1.send(i)

client2.send(i)

baozi_list=["韭菜餡","豬肉大蔥","三鮮餡"]

producer(baozi_list)


python學習之路-day4.1