1. 程式人生 > >python函數三 (裝飾器)

python函數三 (裝飾器)

view **kwargs get 執行 特殊 對象 sleep ret 值轉換

一。函數名(學名:第一類對象)

函數名本質上就是函數的內存地址。通俗點就是特殊的普通變量

def func():
    print(111)
func()
print(func)
# 結果:
# 111
# <function func at 0x00000150713F6048>

1.可以被引用(即可以賦值給其他變量)

def func():
    print(in func)
f = func
f()
# 結果:
# in func

2.可以被當作容器類型的元素

def func():
    print(111)
def func2():
    print(222)
def
func3(): print(333) li = [func(),func2(),func3()] for i in li: i # 結果: 111 222 333

3.可以當作函數的參數和返回值

def func():
    print(111)
func()
def func2():
    return func
f = func2()
f()
# 結果:         從上到下運行,遇見func()後調用函數打印一個111,
# 111            之後到f = func2(),調用func2()返回給f一個值func,
# 111            最後f()即func()再次調用後打印一個111

第一類對象(first-class object)指

1.可在運行期創建

2.可用作函數參數或返回值

3.可存入變量的實體。

二。閉包

閉包的定義:內層函數,對外層函數(非全局)的變量的引用,叫做閉包

閉包的用處:如果說你內存函數是個閉包,python內部有一個機制,遇到閉包

     他會在內存中開啟一個內存空間,不會隨著函數的結束而關閉

技術分享圖片
from urllib.request import urlopen
print(urlopen(http://www.cnblogs.com/jin-xin/articles/8259929.html).read())
def index(url):
    content 
= urlopen(url).read() def get(): with open(爬蟲,a) as f1: f1.write(content.decode(utf-8)) return get index(http://www.cnblogs.com/jin-xin/articles/8259929.html)() index(http://www.cnblogs.com/jin-xin/articles/8259929.html)() index(http://www.cnblogs.com/jin-xin/articles/8259929.html)() index(http://www.cnblogs.com/jin-xin/articles/8259929.html)() index(http://www.cnblogs.com/jin-xin/articles/8259929.html)() def index(): url = "http://www.xiaohua100.cn/index.html" def get(): return urlopen(url).read() return get
爬網頁(閉包用處)

判斷是否是閉包函數:__closure__

ef func():
    name = alex
    def func2():
        print(name)
    func2()
    print(func2.__closure__)               #含有 cell  就是閉包  None  不是閉包
func()
# 結果:
# alex
# (<cell at 0x0000011AD42A75B8: function object at 0x0000011AD6178A60>, <cell at 0x0000011AD42A75E8: str object at 0x0000011AD6177378>)


name = alex
def func():
    def func2():
        print(name)
    func2()
    print(func2.__closure__)                #     None   不是閉包
func()
# 結果:
# alex
# None


def func(x):
    def func2():
        print(x)
    func2()
    print(func2.__closure__)                    
func(alex)
# 結果:
# alex
# (<cell at 0x0000029D98CE75B8: str object at 0x0000029D98D77538>,)

三。在外層函數內部執行內部函數

def func():
    def func2():
        print(111)
    func2()
func()

def func():
    def func2():
        print(111)
    return func2
func()()

四。裝飾器

比如計算一個函數的執行效率

1.最low的寫法

技術分享圖片
import time
def func():
    print(我們都一樣)
start_time = time.time()
time.sleep(0.1)
func()
end_time = time.time()
print(------的執行效率%s%(end_time-start_time))
# 結果:
# 我們都一樣
# ------的執行效率0.10034990310668945
View Code

2.進階寫法

技術分享圖片
import time
def func():
    print(我們都一樣)
def timmer():
    start_time = time.time()
    time.sleep(0.1)
    func()
    end_time = time.time()
    print(------的執行效率%s%(end_time-start_time))
timmer()
# 雖然也可以運行,但是影響了func()的正常運行,還可以在進階
View Code

3.簡單的裝飾器

技術分享圖片
import time
def func():
    print(我們都一樣)
def timmer(f):
    def inner():
        start_time = time.time()
        time.sleep(0.1)
        f()
        end_time = time.time()
        print(------的執行效率%s%(end_time-start_time))
    return inner
func = timmer(func)
func()
# 可以理解為func,timmer,inner通過賦值轉換,加參數,最後只剩一個func,
# 這樣就可以運行程序,又可以知道執行效率
View Code

4.帶返回值的裝飾器(語法糖的用法)

@timmer 相當於 #func = timmer(func) 即待求的函數名 = 新函數名(待求的函數名)

import time
def timmer(func):
    def inner(*args,**kwargs):
        start_time = time.time()
        time.sleep(0.1)
        ret = func(*args,**kwargs)
        end_time = time.time()
        print(------執行效率%s%(end_time-start_time))
        return ret
    return inner

@timmer
def func():
    return 天若有情天亦老,人間正道是滄桑
# func()         打印返回值的話不能寫這步,否則函數會在調用一次,多打印一次執行效率
print(func())
# 結果:
# ------執行效率0.1002659797668457
# 天若有情天亦老,人間正道是滄桑

5.通用裝飾器

def wrapper(func):
    def inner(*args,**kwargs):
        ‘‘‘執行函數前的操作‘‘‘
        ret = func(*args,**kwargs)
        ‘‘‘執行函數後的操作‘‘‘
        return ret
    return inner

@wrapper
def func():
    print(111)
func()

python函數三 (裝飾器)