python3命名空間與作用域,閉包函數,裝飾器
一.命名空間與作用域
命名空間是名字和對象的映射,就像是字典,key是變量名,value是變量的值
1.命名空間
name=‘egon‘ #定義變量 def func(): #定義函數 pass class Foo: #定義類 pass
2.命名空間的分類
(1)內置名稱空間: 隨著python解釋器的啟動而產生,包括異常類型、內建函數和特殊方法,可以代碼中任意地方調用
print(sum) print(max) print(min) print(max([1,2,3])) import builtins for i in dir(builtins): #打印所有的內置函數 print(i)
(2)全局名稱空間:文件的執行會產生全局名稱空間,指的是文件級別定義的名字都會放入該空間
x=1 #全局命名空間 def func(): money=2000 #非全局 x=2 print(‘func‘) print(x) print(func) func()
(3)局部名稱空間:調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定
x=10000 #全局 def func(): x=1 #局部 def f1(): pass
3.作用域
命名空間的可見性就是作用域
- 1. 全局作用域:內置名稱空間,全局名稱空間
- 2. 局部作用域:局部名稱空間
名字的查找順序:局部名稱空間---》全局名層空間---》內置名稱空間
查看全局作用域內的名字:gloabls()
查看局部作用域內的名字:locals()
全局作用域的名字:全局有效,在任何位置都能被訪問到,除非del刪掉,否則會一直存活到文件執行完畢
局部作用域的名字:局部有效,只能在局部範圍調用,只在函數調用時才有效,調用結束就失效
x=1000 def func(y): x=2 print(locals()) print(globals()) func(1)
輸出:
{‘y‘: 1, ‘x‘: 2} {‘__loader__‘: <_frozen_importlib_external.SourceFileLoader object at 0x10c436c88>, ‘__package__‘: None, ‘__cached__‘: None, ‘__file__‘: ‘/Users/hexin/PycharmProjects/py3/day4/2.py‘, ‘func‘: <function func at 0x10c3c9f28>, ‘__builtins__‘: <module ‘builtins‘ (built-in)>, ‘__spec__‘: None, ‘__doc__‘: None, ‘time‘: <module ‘time‘ (built-in)>, ‘__name__‘: ‘__main__‘, ‘x‘: 1000}
四.閉包函數
簡單來說,一個閉包就是你調用了一個函數A,這個函數A返回了一個函數B給你。這個返回的函數B就叫做閉包。
閉包函數須滿足以下條件:
1. 定義在內部函數;
2. 包含對外部作用域而非全局作用域的引用;
def f1(): x = 1 def f2(): print(x) return f2 f=f1() print(f) x=100 f() print(x)
輸出:
<function f1.<locals>.f2 at 0x107714400> 1 100
閉包的應用
from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get oldboy=index(‘http://crm.oldboyedu.com‘) print(oldboy().decode(‘utf-8‘))
五。裝飾器
1.定義
裝飾器:修飾別人的工具,修飾添加功能,工具指的是函數
裝飾器本身可以是任何可調用對象,被裝飾的對象也可以是任意可調用對象
2.為什麽要用裝飾器?
開放封閉原則:對修改是封閉的,對擴展是開放的
裝飾器就是為了在不修改被裝飾對象的源代碼以及調用方式的前提下,為其添加新功能
3.裝飾器的實現
裝飾器的功能是將被裝飾的函數當作參數傳遞給與裝飾器對應的函數(名稱相同的函數),並返回包裝後的被裝飾的函數”
直接看示意圖,其中 a 為與裝飾器 @a 對應的函數, b 為裝飾器修飾的函數,裝飾器@a的作用是:
簡而言之:@a 就是將 b 傳遞給 a(),並返回新的 b = a(b)
def a(name): #與裝飾器對應的函數 return name() @a #裝飾器 b = a(b) def b(): #被裝飾函數 print(‘hexin‘)
輸出
hexin
解析過程是這樣子的:
1.python 解釋器發現@a,就去調用與其對應的函數( a 函數)
2.a 函數調用前要指定一個參數,傳入的就是@a下面修飾的函數,也就是 b()
3.a() 函數執行,調用 b(),b() 打印“hexin”
裝飾器的應用
import time def timmer(func): def wrapper(): start_time=time.time() func() #index() stop_time=time.time() print(‘run time is %s‘ %(stop_time-start_time)) return wrapper @timmer #index=timmer(index) def index(): time.sleep(1) print(‘welcome to index‘) index() 輸出: welcome to index run time is 1.005241870880127 #-------------------------------------------------------------- login_user={‘user‘:None,‘status‘:False} def auth(func): def wrapper(*args,**kwargs): if login_user[‘user‘] and login_user[‘status‘]: res=func(*args,**kwargs) return res else: name=input(‘請輸入用戶名: ‘) password=input(‘請輸入密碼: ‘) if name == ‘hexin‘ and password == ‘123‘: login_user[‘user‘]=‘hexin‘ login_user[‘status‘]=True print(‘\033[45mlogin successful\033[0m‘) res=func(*args,**kwargs) return res else: print(‘\033[45mlogin err\033[0m‘) return wrapper @auth #index=auth(index) def index(): print(‘welcome to index page‘) @auth #home=auth(home) def home(name): print(‘%s welcome to home page‘ %name) index() home(‘hexin‘) 輸出: 請輸入用戶名: heixn 請輸入密碼: 123 login err 請輸入用戶名: hexin 請輸入密碼: 123 login successful hexin welcome to home page
裝飾器的基本框架:
def timer(func): def wrapper(): func() return wrapper
帶參數
def timer(func): def wrapper(*args,**kwargs): func(*args,**kwargs) return wrapper
python3命名空間與作用域,閉包函數,裝飾器