日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

day4----函数-闭包-装饰器

發布時間:2023/12/9 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 day4----函数-闭包-装饰器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
day4----函數-閉包-裝飾器

本文檔內容:

1 python中三種名稱空間和作用域

2 函數的使用

3 閉包

4 裝飾器

一?python中三種名稱空間和作用域

1.1名稱空間:

當程序運行時,代碼從上至下依次執行,它會將變量與值得關系存儲在一個空間中,這個空間 也叫命名空間。例如:name='xingchen' 當程序遇到函數時,它會將函數名存在內存中,函數內部的變量和邏輯暫時不關心; 當函數執行時,內存會臨時開辟一個空間,存放函數體里面的代碼(變量,代碼等),這個空間叫臨時名稱空間 也叫局部名稱空間。 函數外面訪問不到臨時空間的內容;隨著函數的執行完畢,臨時空間會釋放掉。 View Code

python中名稱空間分三種:
  內置名稱空間
  全局名稱空間
  局部名稱空間
作用域:
  全局作用域:
    內置名稱空間
    全局名稱空間
局部作用域:
    局部名稱空間
加載順序
內置名稱空間 ---》全局名稱空間(程序執行時) ---》局部名稱空間(函數執行時)
取值順序:單向不可逆
局部名稱空間 ---》全局名稱空間 ----》內置名稱空間

1.2 ?globals和locals

print(globals() ) 返回的是全局作用域里面的變量與其值,是一個字典

print(locals()) ? 返回的是當前的局部變量與其值,也是一個字典

例如:

def func1():a=1print(a)print(locals())print(globals()) func1() View Code

其結果為:

1{'a': 1}{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000024FD014B240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects-x/s22day03/day4/lianxi.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'func1': <function func1 at 0x0000024FD0056048>} View Code

1.3 global和nonlocal

global:聲明一個全局變量,可以用作局部變量的關鍵字來修改或賦值給全局變量,

    但是:對可變數據類型(list,dict,set)可以直接引用不用通過global。如果默認參數是一個可變的數據類型,那么他在內存中永遠是一個

例如:下面的list就是可變數據類型,因此就不用global

# def extendList(val,list=[]): #    list.append(val) #    return list # list1 = extendList(10) # print('list1=%s'%list1) # [10,] # list2 = extendList(123,[]) # print('list2=%s'%list2) # [123,] # list3 = extendList('a') # print('list3=%s'%list3) #[10,'a']# print('list1=%s'%list1) # print('list2=%s'%list2) # print('list3=%s'%list3)其結果為:[10,a][123][10,a] View Code?

nonlocal:在局部作用域中,對其父級作用域(或者更外層作用域)進行變量賦值或者修改,但是不能修改全局作用域

例如:

def func1():a=1def func2():b=10def func3():nonlocal a,ba=a+1b=b+1print(a,b) #結果為 2,11 func3()print(a,b) #結果為 2,11,func2函數的b被引用了 func2()print(a)        #結果為 2,這里的變量a被引用了,但是b不是在這里面引用的,所以打印b會報錯 func1() View Code

二函數的使用

函數名的本質就是函數的內存地址

1 函數可以被引用

例如:

def func1():print('in func1') f=func1 print(f) 結果為:<function func1 at 0x000001E9313C6048> View Code

2 函數可以作為容器類元素

例如

def func1():print('f1')def func2():print('f2')l1=[func1,func2] l2={'f1':func1,'f2':func2}l1[0]() l2['f2']() View Code

3 函數可以作為返回值

def f1():print('f1')def func1(argv):argv()return argvf = func1(f1) f() View Code

其他: 第一類對象

第一類對象(first-class object)指 1.可在運行期創建 2.可用作函數參數或返回值 3.可存入變量的實體。 View Code

?三 閉包

內部函數包含對外部作用域而非全局作用域變量的引用,該內部函數稱為閉包函數,一般用于裝飾器或者網絡爬取內容

判斷閉包函數的方法__closure__

例如:

def func():name = 'eva'def inner():print(name)print(inner.__closure__) #結果中函數含有cell元素,否則為none return inner f = func() f() View Code

四 裝飾器

?裝飾器的本質是一個python函數,基于閉包函數,讓其他的函數在不改變源碼和調用方式的前提下,增加新的功能

?  裝飾器的應用場景:比如插入日志,性能測試,事務處理,緩存等等場景。

下面看看裝飾器的形成過程:

原始的代碼

import time # print(time.time()) # 1527326532.2688255# def func1(): #   time.sleep(0.3) #    print('非常復雜......') # # start_time = time.time() # func1() # end_time = time.time() # print('此函數的執行效率%s' %(end_time-start_time)) View Code

# 改版1:我要封裝到一個函數中

# def func1(): #    time.sleep(0.3) #    print('非常復雜......') # # def func2(): #    time.sleep(0.3) #    print('特別復雜......') # # func1() # func2() View Code

# # 改版2:被測試函數當參數傳入,可以測試多個函數的執行效率

# def timmer(f): #    start_time = time.time() #   f() #    end_time = time.time() #    print('此函數的執行效率%s' %(end_time-start_time)) # # timmer(func1) # timmer(func2) View Code

# 改版3::測試函數執行效率的同時,不要改變原函數的調用方式。

# def func1(): #   time.sleep(0.3) #   print('非常復雜......') # def func2(): #    time.sleep(0.3) #    print('特別復雜......') # # func1() # # func2() # def timmer(f): #    start_time = time.time() #   f() #   end_time = time.time() #    print('此函數的執行效率%s' % (end_time - start_time)) # f1 = func1 # func1 = timmer # # func1(f1) # timmer(func1) View Code

# 改版4::改版3雖然大體上滿足了我的要求,但是增加兩行代碼,
# 而且多了參數,不好,繼續改,盡量不添加其他代碼,而且做到調用時一模一樣
# 最簡單的裝飾器。

# def func1(): #   time.sleep(0.3) #    print('非常復雜......') # def func2(): #    time.sleep(0.3) #    print('特別復雜......') # # func1() # # func2() # # def timmer(f): # f = func1 函數名 #    def inner(): #     start_time = time.time() #      f() #      end_time = time.time() #     print('此函數的執行效率%s' % (end_time - start_time)) #    return inner # # func1 = timmer(func1) # inner # func2 = timmer(func2) # inner # func1() # inner() # func2() View Code

# 改版5::改版4每次測試一個函數的執行效率時,都需要加一行 func1 = timmer(func1)代碼,麻煩
# python提出了一個語法糖 @。

# def timmer(f): # f = func1 函數名 #    def inner(): #       start_time = time.time() #       f() #       end_time = time.time() #       print('此函數的執行效率%s' % (end_time - start_time)) #    return inner # # @timmer # func1 = timmer(func1) inner # def func1(): #    time.sleep(0.3) #    print('非常復雜......') # # func1() # inner() View Code

# 改版6:被裝飾的函數肯定要有參數的,你現在不能滿足,解決這個問題。
# 被裝飾的函數帶參數的裝飾器

# def timmer(f): # f = func1 函數名 #    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'} #       start_time = time.time() #     f(*args,**kwargs) # f(1,2,,sex='nv',name='alex') #      end_time = time.time() #       print('此函數的執行效率%s' % (end_time - start_time)) #    return inner # # @timmer # func1 = timmer(func1) inner # def func1(a,b): #    time.sleep(0.3) #    print(a,b) #    print('非常復雜......') # # # @timmer # func1 = timmer(func1) inner # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex') #    time.sleep(0.3) #    print(a,b,sex,name) #    print('非常復雜......') # # func2(1,2,sex='nv',name='alex') # inner() View Code

# 改版7:被裝飾的函數肯定要有返回值的,解決這個問題。
# 被裝飾的函數帶參數且有返回值的裝飾器

# def timmer(f): # f = func2 函數名 #    def inner(*args,**kwargs): # args = (1,2),kwargs {sex:'nv',name:'alex'} #       start_time = time.time() #     ret = f(*args,**kwargs) # f(1,2,,sex='nv',name='alex') #       end_time = time.time() #       print('此函數的執行效率%s' % (end_time - start_time)) #      return ret #   return inner # @timmer # func1 = timmer(func1) inner # def func2(a,b,name,sex='man'): # f(1,2,,sex='nv',name='alex') #    time.sleep(0.3) #   print(a,b,sex,name) #    print('非常復雜......') #    return 666 # # print(func2(1,2,sex='nv',name='alex')) # inner()def timmer(f):def inner(*args,**kwargs):start_time = time.time()ret = f(*args,**kwargs)end_time = time.time()print('此函數的執行效率%s' % (end_time - start_time))return retreturn inner @timmer # def func2(a,b,name,sex='man'): #    time.sleep(0.3) #    print(a,b,sex,name) #    print('非常復雜......') #    return 666 # # ret1 = func2(1,2,sex='nv',name='alex') # print(ret1) View Code 至此裝飾器的固定結構如下 def timer(func):def inner(*args,**kwargs):'''執行函數之前要做的'''re = func(*args,**kwargs)'''執行函數之后要做的'''return rereturn inner View Code

?但是如何函數有很多,如何取消他們呢,以后如果又加上呢---帶參數的裝飾器模型

def outer(flag):def timer(func):def inner(*args,**kwargs):if flag:print('''執行函數之前要做的''')re = func(*args,**kwargs)if flag:print('''執行函數之后要做的''')return rereturn innerreturn timer@outer(False) #改為false是不執行裝飾器內的內容 def func():print(111)func() View Code

如果多個裝飾器裝飾一個函數呢

def wrapper1(func):def inner():print('wrapper1 ,before func')func()print('wrapper1 ,after func')return innerdef wrapper2(func):def inner():print('wrapper2 ,before func')func()print('wrapper2 ,after func')return inner@wrapper1 @wrapper2 def f():print('in f') f() View Code

其結果為:

wrapper1 ,before func wrapper2 ,before func in f wrapper2 ,after func wrapper1 ,after func View Code

?裝飾器的另外一種方法:

import functools def wrapper(func):@functools.wraps(func)def inner(*args, **kwargs):print('我是裝飾器')return func(*args,**kwargs)print('--------')return inner@wrapper def index():print('我是被裝飾函數')return None

index()

?

?

?

---------------------------------------------------------------------------------回頂部----------------------------------------------------------------------------------------------------------------------------

posted on 2018-05-30 10:16 dawn-liu 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/mmyy-blog/p/9109425.html

總結

以上是生活随笔為你收集整理的day4----函数-闭包-装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。