python基礎之閉包函式和裝飾器

2022-08-20 11:24:14 字數 4859 閱讀 6170

補充:全域性變數宣告及區域性變數引用

python引用變數的順序: 當前作用域區域性變數->外層作用域變數->當前模組中的全域性變數->python內建變數

global關鍵字用來在函式或其他區域性作用域中使用全域性變數,宣告後可以在其他作用於中修改和使用

x=1      #全域性賦值變數

def foo():

global x    #函式內部全域性宣告變數x

x=1111111    #函式內部修改全域性變數x

print(x)

foo()

print(x)

global宣告的變數在任何作用域都能夠修改,所以一般非必要情況下要避免這種宣告操作。

nonlocal關鍵字用來在函式或其他作用域中使用外層(非全域性)變數,一般用在函式巢狀。

def f1():

# x=2

def f2():

x=3def f3():

nonlocal x

x=1111

# print('f3',x)

f3()

print('f2',x)

f2()

# print('f1',x)

f1()

如上,如果在f3的函式體內部不做nonlocal宣告x,即將nonlocal x注釋掉,那麼函式體f2內的print將列印的結果是「f2 3」,宣告後的結果為「f2 1111」。

閉包函式

閉包函式定義:

函式內部定義的函式稱為內部函式,該內部函式包含對外部(上層)作用域,而不是對全域性作用域名字的,那麼該內部函式稱為閉包函式

定義閉包函式:

定義閉包函式的基本形式

def 外部函式名():

內部函式需要的變數

def 內部函式(): #基本函式

引用外部的變數

return 內部函式 #不加括號,返回記憶體位址

閉包函式指的是內部函式

閉包函式包含對外部作用域的引用,而非全域性作用域的引用

閉包函式的特點:自帶向外的作用域,延遲計算(惰性計算,用到的時候計算)

示例:

name='alex'    #全域性定義的變數

def func():    

name='egon'  #函式func呼叫的變數,外部作用域

def bar():    #內部函式

print(name)  #內部函式bar列印name的作用域除了bar函式自己本身,還有func函式內部

return bar    #呼叫func函式時的返回值為bar函式本身,而非bar函式執行結果,返回的是bar函式的一段記憶體位址

b=func()      #b接收func函式的返回值,即bar函式的記憶體空間,現在的b就等於是bar

print(b)

b()        #執行b即執行bar函式的print(name)列印操作,而非全域性定義的name

#print(b.__closure__[0].cell_contents) #返回作用域空間的第乙個變數值

#print(b.__closure__) #作用域空間資訊

輸出結果

.bar at 0x0000021ca66cb8c8>

egon

自帶向外的作用域,即bar函式包含func函式的作用域,也包含bar本身的作用域,即bar能夠呼叫name='egon'

作用域在函式定義的時候已經固定了,也就是說,無論在什麼地方呼叫b(),b函式的作用域永遠用的是bar函式定義時候的作用域。

裝飾器基礎

程式源**的原則:對功能擴充套件開放,對修改源**封閉

即可以在源**的基礎上擴充套件功能,而不能修改源**(原因是,系統上線了修改源**,改錯了咋整)

裝飾器就是用來進行源**功能能擴充套件的一種實現方式。

裝飾器本質上是任意可呼叫的物件,目前能夠理解的就是是函式,而被裝飾的物件也可以是任意可呼叫的物件。

裝飾器功能:是在不修改被裝飾物件源**以及被裝飾物件的呼叫方式的前提下,為其新增新功能

裝飾器原則:不修改源**,不修改呼叫方式,還要能夠增加新功能

示例一:當呼叫函式index時候,隨機等待0-4秒列印hello world

#原功能

import time

import random

def index():

time.sleep(random.randrange(1,5))

print('hello world')

index()

示例二:擴充套件功能統計index的執行時間,包括隨機等待的時間

import time

import random

def index_new(func):

def timmer():

start_time=time.time()

func()

stop_time=time.time()

print('time:%s' %(stop_time-start_time))

return timmer

def index():    #源**並不改變

time.sleep(random.randrange(1,5))

print('hello world')

index=index_new(index)

index()

輸出結果:

hello world

time:3.000032663345337

示例三:裝飾器呼叫語法

def index_new(func):

def timmer():

start_time=time.time()

func()

stop_time=time.time()

print('time:%s' %(stop_time-start_time))

return timmer

#使用@符號進行呼叫

@index_new #index=index_new(index)

def index():

time.sleep(random.randrange(1,5))

print('hello world')

index()

示例四:定義多個裝飾器,增加多個功能模組

import time

import random

#裝飾器1:計時模組

def timmer(func):

start_time = time.time()

func()

stop_time=time.time()

print('run time is %s' %(stop_time-start_time))

#裝飾器2:認證模組

def auth(func):

def deco():

name=input('name: ')

password=input('password: ')

if name == 'egon' and password == '123':

print('login successful')

else:

print('login err')

return deco

#被裝飾函式

def index():

# time.sleep(random.randrange(1,5))

time.sleep(3)

print('welecome to index page')

#並沒有呼叫任何裝飾器

def home():

time.sleep(random.randrange(1,3))

print('welecome to home page')

index() #deco()

home()

當要呼叫多個裝飾器的時候,呼叫的順序是,誰先執行就先呼叫哪乙個,順序是從上而下,但是內部計算的順序是從下而上的

示例五:源**需要傳入引數的,以及需要返回值的

import time

import random

#裝飾器

def timmer(func):

start_time = time.time()

res=func(*args,**kwargs)    #返回值賦值,需要傳入的函式有返回值才行

stop_time=time.time()

print('run time is %s' %(stop_time-start_time))

return res    #丟擲返回值

#被裝飾函式

@timmer

def index():

time.sleep(random.randrange(1,5))

print('welecome to index page')

@timmer

def home(name):

time.sleep(random.randrange(1,3))

print('welecome to %s home page' %name)

return 123123123123123123123123123123123123123123

res1=index()

print('index return %s' %res1)

res2=home('egon') #wraper()

print('home return %s' %res2)

python基礎 lambda 冒泡 閉包和裝飾

python使用lambda建立匿名函式 foo 18,9,22,17,24,8,12,27 print list filter lambda x x 3 0,foo print list map lambda x x 2 10,foo import functools,functools def ...

python函式閉包和遞迴 函式和閉包之尾遞迴

前面提到過,如果想把更新var的while迴圈轉換成僅使用val這種更函式式的風格的話,有時候你可以使用遞迴。下面的例子是通過不斷改善猜測數字來逼近乙個值的遞迴函式 var guess initialguess while isgoodenough guess guess improve guess...

python基礎 閉包函式

內包函式定義 內部函式包含對外部作用域而非全劇作用域名字的引用,該內部函式稱為閉包函式 函式內部定義的函式稱為內部函式 一 建立乙個閉包 使用外層函式的變數也是閉包 使用外層函式的形參也是閉包 def outter 本質就是 記憶體空間 name zs def inner print name 引用...