1. 程式人生 > >閉包函數和裝飾器

閉包函數和裝飾器

imm args .text 需要 開放封閉原則 ret fun 其他 dex

     閉包函數

#作用域關系在函數定義階段時就已經固定死了,與調用位置無關
# 即:在任意位置調用函數都需要跑到定義函數時尋找作用域關系

# def f1():
# x=1
# def inner():
# print(x) #x最後還是等於1,因為只看定義階段,
#
# return inner
#
# func=f1()
#
# def f2():
# x=111111
# func()
#
# f2()

# 閉包函數:
# 閉指的是:該函數是一個內部函數
# 包指的是:指的是該函數包含對外部作用域(非全局作用域)名字的引用
# def outter():
# x = 1
# def inner():
# print(x)
#
# return inner #outter()拿到的是inner的地址。
#
# f=outter()
#
# def f2():
# x=1111111
# f()
#
# f2()
#
#
# def f3():
# x=4444444444444
# f()
#
# f3()

# 註意:當函數體需要傳值的時候,有兩種方法:


# 為函數體傳值的方式一:使用參數的形式
# def inner(x):
# print(x)
#
# inner(1)
# inner(1)
# inner(1)
# 為函數體傳值的方式二:包給函數
‘‘‘
def outter(x):
# x=1 #相當於把x=1包給了inner
def inner():
print(x)
return inner

f=outter(1) #f=inner
f()
‘‘‘

# 閉包函數的應用場景一:再爬蟲下載網站的時候:
# 第一種用傳參的方式:
# import requests
#
# def get(url):
# response=requests.get(url)
# if response.status_code == 200:
# print(response.text)
#
# get(‘https://www.baidu.com‘)
# get(‘https://www.baidu.com‘)
# get(‘https://www.baidu.com‘)
#
# get(‘https://www.python.org‘)
# get(‘https://www.python.org‘)
# get(‘https://www.python.org‘)
# get(‘https://www.python.org‘)


第二種用閉包函數的方式:
import requests

def outter(url):
# url=‘https://www.baidu.com‘
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
return get

baidu=outter(‘https://www.baidu.com‘)
python=outter(‘https://www.python.org‘)


baidu()
baidu()

python()
python()



裝飾器


1、什麽是裝飾器
器指的是工具,而程序中的函數就具備某一功能的工具
裝飾指的是為被裝飾器對象添加額外功能

就目前的知識來看:
定義裝飾器就是定義一個函數,只不過該函數的功能是用來為
其他函數添加額外的功能

其實:
裝飾器本身其實可以是任意可調用的對象
被裝飾的對象也可以是任意可調用的對象


2、為什麽要用裝飾器
軟件的維護應該遵循開放封閉原則
開放封閉原則指的是:
軟件一旦上線運行後對修改源代碼是封閉的,對擴展功能的是開放的
這就用到了裝飾器

裝飾器的實現必須遵循兩大原則:
1、不修改被裝飾對象的源代碼
2、不修改被裝飾對象的調用方式
裝飾器其實就在遵循1和2原則的前提下為被裝飾對象添加新功能

3、如何用裝飾器
‘‘‘

# import time
#
# def index():
# start=time.time()
# print(‘welcom to index‘)
# time.sleep(3)
# stop=time.time()
# print(‘run time is %s‘ %(stop-start))
# index() #這種方式改變了原代碼

# import time
#
# def index():
# print(‘welcom to index‘)
# time.sleep(3)
#
# def f2():
# print(‘from f2‘)
# time.sleep(2)
#
# start=time.time()
# index()
# stop=time.time()
# print(‘run time is %s‘ %(stop-start))
#
# start=time.time()
# f2()
# stop=time.time()
# print(‘run time is %s‘ %(stop-start))









# import time
#
# def index():
# print(‘welcom to index‘)
# time.sleep(3)
#
# def timmer(func):
# start=time.time()
# func()
# stop=time.time()
# print(‘run time is %s‘ %(stop-start))
#
# timmer(index)




‘‘‘
import time

def index():
print(‘welcom to index‘)
time.sleep(3) #被裝飾函數的原代碼

def timmer(func): #func=最原始的index
# func=index
def inner():
start=time.time()
func() #調用外層包給inner的值,
stop=time.time()
print(‘run time is %s‘ %(stop-start))
return inner

# f=timmer(index)
# f()

# index=timmer(被裝飾函數的內存地址)
index=timmer(index) #index=inner

index() #inner()


‘‘‘
import time

def index():
print(‘welcom to index‘)
time.sleep(3)

def timmer(func):
#func=最原始的index
def wrapper():
start=time.time()
func()
stop=time.time()
print(‘run time is %s‘ %(stop - start))
return wrapper

index=timmer(index) #index=wrapper函數的內存地址
index()


裝飾器修正


# import time
#
# def index():
# print(‘welcome to index‘)
# time.sleep(3)
# return 123
#
# def home(name):
# print(‘welcome %s to home page‘ %name)
# time.sleep(2)
#
#
# def timmer(func):
# #func=最原始的index
# def wrapper(*args,**kwargs):
# start=time.time()
# res=func(*args,**kwargs) #把func賦值給res,是為了讓變化過的index和最原始的index返回值一樣,其實就是多賦值了一個變量
# stop=time.time()
# print(‘run time is %s‘ %(stop - start))
# return res
# return wrapper
#
#
# index=timmer(index)
# home=timmer(home)
#
# res=index()
# home(‘egon‘)


 

閉包函數和裝飾器