一、函數對象:
函數名就相當於變量名,把函數的內存地址當作一種變量值(一種數據類型)去使用
在面向對象編程中,一切皆對象
具體的體現:
1.函數可以被引用
2.函數可以作爲函數的參數
3.函數可以作爲函數的返回值
4.函數可以存儲到容器類型中
二、函數嵌套:
1.嵌套定義
def outer():
def inner():
pass
2. 嵌套調用
def max2(x, y):
if x > y:
return x
else:
return y
def max4(a, b, c, d):
res1 = max2(a.b)
res2 = max2(res1, c)
res3 = max2(res2, d)
return res3
三、名稱空間和作用域
名稱空間:
1.什麼是名稱空間:
存放名字與值內存地址綁定關係的地方
x=10
x:10的內存地址
2.爲什麼要有名稱空間:
3.如何用內存空間:
內置名稱空間:存放py解釋器自帶的函數名稱
parcharm解釋器啓動時創建,關閉解釋器時銷燬
全局名稱空間:文件級別的名稱:除了內置名稱和函數內名稱,其餘都是全局名稱
運行文件時創建,所有文件運行結束或者中途刪除時銷燬
局部名稱空間:函數內定義的名稱
調用函數時創建,函數執行完畢銷燬
查找名稱順序:
1.查找名字的順序是從當前位置往外查找
2.名稱空間的嵌套關係是在函數定義階段就固定死的,與調用的位置沒關係
函數的作用域在定義時就固定了,與調用的位置沒關係
名稱空間的加載順序:
內置>全局>局部
名稱空間的查找順序:
局部>全局>內置 (不能反着找)
作用域:
域指的是區域、範圍
即全局範圍:全局存活 全局有效
無論在任何位置都能看的到
全局的名稱空間和內置的名稱空間 在使用上沒什麼區別
局部的和全局的內置的 就有區別了 局部定義的只能在局部使用
全局的 和 內置的可以劃分爲同一個範圍
global 表示的是全局範圍 就是所謂的全局作用域
局部的單獨一個範圍
local 局部作用域
globals() 查看全局作用域中的內容
locals()查看局部作用域中的內容 (相對局部,站在什麼位置看就是哪個局部,
比如你在全局作用域中使用locals,看到的就是全局作用域的內容)
四、閉包函數:
1.什麼是閉包函數
閉函數:該函數一定是定義在函數內的函數
包函數:該內部函數包含對外層函數作用域名字的引用
2.爲何要用閉包函數
傳值
3.如何用
爲函數體傳值的方案一:直接參數傳
def f():
print(x)
爲函數體傳值的方案二:閉包傳值
def outer(x):
def f():
print(x)
return f
f1 = outer(10)
f2 = outer(11)
f1()
f2()
五、裝飾器
1.什麼是裝飾器
裝飾器指的是爲被裝飾對象添加新功能的工具
裝飾器本身可以是任意可調用的對象
被裝飾對象本身也可以是任意可調用對象
2.爲何要用裝飾器
開放封閉原則:對修改封閉,對擴展開放
裝飾器的原則:
1.不能修改被裝飾對象的源代碼
2.不能修改被裝飾對象的調用方式
裝飾器的目的:
就是在遵循原則1和2的前提下,爲被裝飾對象添加新功能
3.如何用
1.源函數
def index():
time.sleep(1)
print('welcome to index page')
2.添加功能
import time
def index():
time.sleep(1)
print('welcome to index page')
def outer(func):
# func=最原始那個index的內存地址
def wrapper(*args,**kwargs):
start_time = time.time()
res=func(*args,**kwargs):#最原始那個index的內存地址
end_time = time.time()
print('time is %s' %(end_time - start_time))
return res
return wrapper
index=outer(index) #index=outer(最原始那個index的內存地址) index=wrapper的內存地址
index() #wrapper的內存地址()
# 偷樑換柱 用戶並不知道
3.語法糖
import time
def outer(func):
# func=最原始那個index的內存地址
def wrapper(*args,**kwargs):
start_time = time.time()
res=func(*args,**kwargs):#最原始那個index的內存地址
end_time = time.time()
print('time is %s' %(end_time - start_time))
return res
return wrapper
@outer #index=outter(index)
def index():
time.sleep(1)
print('welcome to index page')
index()
總結:
要寫一個裝飾器,先定義一個新函數例如def inner():,寫要添加的功能,寫好之後打包。
所謂打包其實有固定的套路,在新函數同級頭下寫return inner,在新函數同級頭上寫參數func=index(index爲源函數名)
定義一個外函數def outer():,將寫好的新函數上下三行,統一縮進,打包進外函數內。就可以了
使用語法糖,調用裝飾器運行源函數即可。