装饰器 闭包 生成器 迭代器
2018-02-21? 16:15:56
定義:本質(zhì)是函數(shù),(裝飾其他函數(shù))為其他函數(shù)增加附加功能
裝飾器原則
說白了,就是被裝飾函數(shù)不知道裝飾器的存在
?
裝飾器的知識儲備
函數(shù)即變量
高階函數(shù)
把一個函數(shù)名當(dāng)作實參傳給另外一個函數(shù)
def ball():# print('I am ball')
# # return 15
# def text11(hh):
# hh()
# text11(ball) # (函數(shù)后面有括號是這個函數(shù)本身和return,text11(ball())不符合高階函數(shù) 沒有括號是內(nèi)存地址)
???????
?
返回值可以是函數(shù)名
?
嵌套函數(shù)
?
?裝飾器本質(zhì)上是一個python函數(shù),他可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值是一個函數(shù)對象. 經(jīng)常用于有切面需求的場景,比如:插入日志,性能測試,事物處理,緩存,權(quán)限校驗等場景. 裝飾器是解決這類問題的絕佳設(shè)計,有了裝飾器,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)使用.?? 裝飾器就是為已經(jīng)存在的對象添加額外的功能
?
@符號是裝時器的語法糖,在定義函數(shù)時使用,避免再一次賦值操作
1起源
我們想在login中輸入調(diào)試信息,我們可以這樣做
def login():print('in login')
def printdebug(fun):
print('enter the login')
fun()
print('exit the login')
printdebug(login)
?2讓代碼變得優(yōu)美一點
def login():print('in login')
def printdebug(fun):
def a():
print('enter the login')
fun()
print('exit the login')
return a
debug_login = printdebug(login)
debug_login()
3 讓代碼變得更加優(yōu)美(python提供了@u語法糖符號)
def printdebug(fun):def a():
print('enter the login')
fun()
print('exit the login')
return a
@printdebug
def login():
print('in login')
login()
4.加上參數(shù)
1)被裝飾函數(shù)加參數(shù)
python會將login的參數(shù)直接傳給函數(shù)a. 我們可以在函數(shù)a中使用user變量
def printdebug(fun):def a(user):
print('enter the login in ')
fun(user)
print('exit the login')
return a
@printdebug
def login(user):
print('in login'+ user)
4.2裝飾器本身有參數(shù)(為了接受傳來的參數(shù),需要在原本的printdebug函數(shù)上面添加一個函數(shù)來接收參數(shù))
def printdebug_level(level):
def printdebug(fun):
def a(user):
print('enter the login, and debug level is %s'%level)
fun(user)
print('exit the login')
return a
return printdebug
@printdebug_level('it')
def login(user):
print('in login %s'%user)
login('dsaf')
5 裝飾有返回值的函數(shù)(在裝飾器中,將被裝飾函數(shù)賦給一個變量,然后返回這個變量)
def printdebug(fun):
def a(user):
print('enter the login, and debug level is %s'%level)
fun(user)
retuu = fun(user)
print('exit the login')
return retuu
return a
return printdebug
@printdebug_level('it')
def login(user):
print('in login %s'%user)
return '555'
res = login('dsaf')
print('my name is %s'%res)
?
閉包
如果一個函數(shù)定義在另一個函數(shù)的作用域內(nèi),并且引用了外層函數(shù)的變量,稱為閉包def outter():
name = 'slz'
def inner():
print(name)
return inner
res = outter()
res()
print(res.__closure__) 如果res是閉包的話,會返回一個由cell對象組成的元組對象 print(res.__closure__[0].cell_contents) cell_contents屬性是閉包中的自由變量 列表生成器
將列表中的每個值加一
a = [i+1 for i in range(10)]
print(a)
生成器
通過列表生成器,我們直接創(chuàng)建了一個列表.但是受到內(nèi)存限制,列表容量肯定是有限是的.
而且,創(chuàng)建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅訪問前面的幾個元素,那后面的大多數(shù)元素占用的空間就白白浪費了
所以,如果列表和i元素可以按照某種算法推算出來,那我們是否可以在循環(huán)的過程中不斷推算出后續(xù)的元素呢?
這樣就不必創(chuàng)建完整的list,從而節(jié)省大量的空間
在python中,這種一邊循環(huán)一邊計算的機制,稱為生成器: generator
要創(chuàng)建一個generator,有很多種方法,第一種很簡單,只要把列表生成式的[]改為()
b = (i+1 for i in range(10))
print(b)
那么我們?nèi)绾伟裝的值打印出來呢
b = (i+1 for i in range(10))print(b)
for n in b:
print(n)
定義generator的另一種方法,如果一個函數(shù)定義中包含yield關(guān)鍵字,那么這個函數(shù)就不在是一個普通函數(shù),而是一個generator
def fib(max):n,a,b = 0,0,1while n < max:#print(b) yield b a,b = b,a+b n += 1 return 'done'還是通過循環(huán)來調(diào)用
for i in fib(19):
print(i)
可迭代對象
就是可以用for循環(huán)的for a in 'abc':
print(a)
一類是集合數(shù)據(jù)類型,如list,tuple,dict,set,str
一類是generator,包括生成器
測試某個數(shù)據(jù)是否可迭代
1, 就是上面的可以直接作用于for循環(huán)的統(tǒng)稱為可迭代對象: Iterable
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
2 for i in 100:
print(i)
迭代器
*可以被next()函數(shù)調(diào)用并不斷返回下一個值的對象稱為迭代器:Iterator。
可以使用isinstance()判斷一個對象是否是Iterator對象:
| 1 2 3 4 5 6 7 8 9 | >>> from collections import Iterator >>> isinstance((x for x in range(10)), Iterator) True >>> isinstance([], Iterator) False >>> isinstance({}, Iterator) False >>> isinstance('abc', Iterator) False |
這是因為Python的Iterator對象表示的是一個數(shù)據(jù)流,Iterator對象可以被next()函數(shù)調(diào)用并不斷返回下一個數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時拋出StopIteration錯誤。可以把這個數(shù)據(jù)流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數(shù)實現(xiàn)按需計算下一個數(shù)據(jù),所以Iterator的計算是惰性的,只有在需要返回下一個數(shù)據(jù)時它才會計算。
Iterator甚至可以表示一個無限大的數(shù)據(jù)流,例如全體自然數(shù)。而使用list是永遠不可能存儲全體自然數(shù)的。
Iterator是只有需要返回下一步運算的時候才會計算
??小結(jié)
凡是可作用于for循環(huán)的對象都是Iterable類型;
凡是可作用于next()函數(shù)的對象都是Iterator類型,它們表示一個惰性計算的序列;
集合數(shù)據(jù)類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個Iterator對象。
Python的for循環(huán)本質(zhì)上就是通過不斷調(diào)用next()函數(shù)實現(xiàn)的,例如:
| 1 2 | for x in [1, 2, 3, 4, 5]: ????pass |
實際上完全等價于:
# 首先獲得Iterator對象: it = iter([1, 2, 3, 4, 5]) # 循環(huán): while True: try: # 獲得下一個值: x = next(it) except StopIteration: # 遇到StopIteration就退出循環(huán) break轉(zhuǎn)載于:https://www.cnblogs.com/sunlizhao/p/8457446.html
總結(jié)
以上是生活随笔為你收集整理的装饰器 闭包 生成器 迭代器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人工智能---机器学习
- 下一篇: USACO-Section1.2 Fri