1. 程式人生 > >day13 多個裝飾器疊加 生成式

day13 多個裝飾器疊加 生成式

1.裝飾器剩餘

from functions import wraps

@wrap(func) 會把func內的自帶方法賦給wrapper,這樣wrapper裝飾函式就和原函式一模一樣

多個裝飾器疊加

def outter1(func):

  def wrapper1(*args,**kwargs):

    res = func(*args,**kwargs)

    return res

  return wrapper1

 

def outter2(func):

  def wrapper2(*args,**kwargs):

    res = func(*args,**kwargs)

    return res

  return wrapper2

 

def outter3(func):

  def wrapper3(*args,**kwargs):

    res = func(*args,**kwargs)

    return res

  return wrapper3

 

@outer1

@outer2

@outer3

def f1(name):

  print('welcome home %s' % name)

 

f1('egon')

載入順序

自下而上,因為裝飾器的語法糖,相當於f1 = outer1(outer2(outer3(f1)))

檢測語法後,先載入outer3,此時的原函式f1的記憶體地址還沒有變包在閉包函式wrapper3中傳給outer2,outer2將打包的閉包函式wrapper2地址傳給outer1,outer1將打包的閉包函式打包給f1

outer1(outer2(outer3(f1))) 從右往左一步一步閉包並且載入函式

 

執行順序 從上往下,因為用到的閉包函式都被包給了outer1中,先去outer1中開始執行,執行到其中要執行wrapper2的地方了,這時wrapper1還沒執行完,就跳到wrapper2中去執行,wrapper2還沒執行完,遇到wrapper3了,就跳到wrapper3中執行,執行完已經是最內層了,開始把wrapper3的返回值返回值給wrapper2,wrapper2執行完返回值返回給wrapper1,wrapper1執行完之後,返回值返回給最初始的函式,繼續執行全域性程式碼,整個裝飾器函式的呼叫結束。

 

 

2.有參裝飾器

以上裝飾器模版如下

from functools import wraps

def outter(func):

  @wraps(func)

  def wrapper(*args,**kwargs):

    res = func(*args,**kwargs)

    return res

  return wrapper

這樣會遇到一個問題,這個函式確實可以完全模仿了舊函式的同時加了新功能,但是如果假如想給內部閉包函式傳進其他引數方便使用,在當前模版上就沒法做到

outter(func)的引數必須是原函式,不能增加,也不能減少,否則使用語法糖@outter func=outter(func)會報錯

另外,wrapper(*args,**kwargs)內傳的引數也不能改變,這是為了把原函式的引數原封不動還給原函式去呼叫

這個時候,就可以再多包一層函式,在最外層函式傳引數,而且引數可以任意指定,把最外層函式名返回,這樣包含著最外層名稱空間的閉包函式就賦給了原函式

既包含舊功能,又添加了新功能,還傳了新引數,可供程式擴充套件使用

 

 

 根據傳進的檔案型別不同,在內部增加判斷選擇寫入檔案的方式

 

3.三元表示式

三元表示式用來在保證程式碼可讀性的前提下,精簡一些語句的寫法

如下需要函式判斷兩個數的大小語句

def max(x,y)

  if x>y:

    return x

  else:

    return y

可以用如下表達式代替

 

x=10

y=20

res = x if x >y else y #b表示式1 if條件表示式 else 表示式2,當if判斷返回True時,返回結果表示式1,否則返回結果表示式2

print(res)

 

res = ’ok‘ if False else 'No'

print(res) 

 

 

4.生成式:用來生成資料的表示式

先來生成一個列表

l = []

for i in range(10):

  if i >4:

    l.append(i**2)

列表生成式

l = [i**2 for i in range(10) if i >4] 不能加else,因為不知道是加給for的還是if的

print(l)

 

 

name = ['egon','alex_sb','kevin_sb','hxx_sb','cxx_sb'] 匹配找出結尾是sb的元素

sbs=[]

for name in names:

  if name.endswith('sb')

    sbs.append(name)

用生成式代替

sbs = [name for name in names if name.endswith('sb')]

 

print([name.upper() for name in names])

 

字典生成式

 

res = {i:i**2 for i in range(10) if i > 3}

print(res)

print({i for i in 'hello'}) 生成集合,去重

 

5.匿名函式

先看有名函式

def func():

  print(‘from func’)

func()

func()

func()

有名稱的函式定義後,可以在之後多次以名字呼叫

 

匿名函式就是隻定義一個函式的記憶體地址,主要用於臨時使用一次的場景

 

func = lambda x,y:(return)x+y 匿名函式自動返回值,不用新增return

print(func)

print(func(1,2))

res = (lambda x,y:x+y)(1,2) 匿名函式後面加扣號呼叫,並傳引數

 

print(max([10,11,-3,23]))

 

salaries = {

'egon':3000

'alex':100000000

'wupeiqi':10000

'yuanhao':2000

}

def func(k):

  return salaries[k]

 

print(max(salaries,key = lambda  k:salaries[k]))