補充:全域性變數宣告及區域性變數引用
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 timeimport 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 timeimport 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 timeimport 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 引用...