1. 裝飾器
- 裝飾器他人的器具,本身可以是任意可調用對象,被裝飾者也可以是任意可調用對象。
- 強調裝飾器的原則:1 不修改被裝飾對象的源代碼 2 不修改被裝飾對象的調用方式
- 裝飾器的目標:在遵循1和2的前提下,為被裝飾對象添加上新功能
- 開放封閉原則:對修改封閉,對擴展開放
import timedef timmer(fun):start_time=time.time()fun()end_time=time.time()def fun1():print("in func1")timmer(fun1) #改變了原先函數的執行
import timedef timmer(fun):def inner():start_time=time.time()fun()end_time=time.time()print("run in {} time {}".format(fun,end_time-start_time))return inner #實際上是把函數名字傳遞給timmer,timmer執行,之所以返回inner是因為inner在全局不可以被調用def fun1():print("in func1")print(timmer(fun1)) #可以運行,其實就是執行Inner,目的就是在全局可以調用,
fun1=timmer(fun1) #函數本身就是變量,變量值互換
fun1()
-
這樣最基本的裝飾器就完成了,Python為我們提供了語法糖,一個完整的裝飾器如下:會允許函數傳參并且返回值不變
import timedef timmer(fun):def inner(*args,**kwargs):start_time=time.time()ret = fun(*args,**kwargs)end_time=time.time()print("run in {} time {}".format(fun,end_time-start_time))return retreturn inner #實際上是把函數名字傳遞給timmer,timmer執行,之所以返回inner是因為inner在全局不可以被調用@timmer
def fun1(num):print("in func1 {}".format(num))return 123# print(timmer(fun1)) #可以運行,其實就是執行Inner,目的就是在全局可以調用,
# fun1=timmer(fun1) #函數本身就是變量,變量值互換
print(fun1(1))
-
這樣可以修飾多個函數,但是要批量更改該怎么,如果不想裝飾了,需要挨個去掉嗎
import timedef outer():Flag=Falsedef timmer(fun):def inner(*args,**kwargs):if Flag:start_time=time.time()ret = fun(*args,**kwargs)end_time=time.time()print("run in {} time {}".format(fun,end_time-start_time))return retelse:ret = fun(*args, **kwargs)return retreturn inner #實際上是把函數名字傳遞給timmer,timmer執行,之所以返回inner是因為inner在全局不可以被調用return timmer @outer() #之所以加執行就是把outer的返回值timmer函數的內存地址放在這里,其實就是@timmer
def fun1(num):print("in func1 {}".format(num))return 1@outer()
def fun2(num):print("in func2 {}".format(num))return 2@outer()
def fun3(num):print("in func3 {}".format(num))return 3print(fun1(1))
print(fun2(2))
print(fun3(3))
-
編寫裝飾器,為多個函數加上認證的功能(用戶的賬號密碼來源于文件),要求登錄成功一次,后續的函數都無需再輸入用戶名和密碼
-
使用小知識點eval
login_status={"user":None,"status":False}def outer():Flag=Truedef auth(func):def inner(*args,**kwargs):if Flag:with open("user.txt",encoding="utf-8") as read_f:if login_status['user'] and login_status['status']:ret = func(*args, **kwargs)return retuser_info=eval(read_f.read())name=input("your name>>:").strip()password=input("your password>>:").strip()if name in user_info and user_info[name]["password"] == password:login_status["user"]=namelogin_status["status"]=Trueprint(login_status)ret = func(*args,**kwargs)return retelse:print("bad")else:ret = func(*args, **kwargs)return retreturn innerreturn auth@outer()
def fun1():print("in func1")return 1@outer()
def fun2():print("in func2")return 2@outer()
def fun3():print("in func3")return 3fun1()
fun2()
fun3()
def wrapper1(func):def inner():print('wrapper1 ,before func')func()print('wrapper1 ,after func')return innerdef wrapper2(func):def inner():print('wrapper2 ,before func')func()print('wrapper2 ,after func')return inner@wrapper2
@wrapper1
def f():print('in f')f()
結果原因如下:從后分析
?裝飾器小練習:
#編寫下載網頁內容的函數,要求功能是:用戶傳入一個url,函數返回下載頁面的結果
import time
from urllib.request import urlopendef wrapper(func):def inner(*args,**kwargs):start_time=time.time()ret = func(*args,**kwargs).decode('utf-8')end_time=time.time()print("{} time is {}".format(*args,end_time-start_time))return retreturn inner@wrapper
def get(url):return urlopen(url).read()# print(get('http://www.baidu.com'))
get('http://www.baidu.com')
2. 迭代器
-
?其實迭代就是我們說的,可以將某個數據集內的數據“一個挨著一個的取出來”,就叫做迭代。
- 可迭代協議的定義非常簡單,就是內部有了__iter__方法。
from collections import Iterablel = [1, 2, 3, 4]
t = (1, 2, 3, 4)
d = {1: 2, 3: 4}
s = {1, 2, 3, 4}print(isinstance(l, Iterable))
print(isinstance(t, Iterable))
print(isinstance(d, Iterable))
print(isinstance(s, Iterable))
print(dir([1,2]))
l=[1,2,3,4]
l_iter=l.__iter__() #先把可迭代對象變成迭代器
print(l_iter.__next__()) #依次取值
print(l_iter.__next__()) #依次取值
print(l_iter.__next__()) #依次取值
print(l_iter.__next__()) #依次取值
l=[1,2,3,4]
l_iter=l.__iter__() #先把可迭代對象變成迭代器
# print(l_iter.__next__()) #依次取值
# print(l_iter.__next__()) #依次取值
# print(l_iter.__next__()) #依次取值
# print(l_iter.__next__()) #依次取值while True:try:item = l_iter.__next__()print(item)except StopIteration:break
3. 生成器
-
一個包含yield關鍵字的函數就是一個生成器函數。yield可以為我們從函數中返回值
-
但是yield又不同于return,return的執行意味著程序的結束,調用生成器函數不會得到返回的具體的值,而是得到一個可迭代的對象。
-
每一次獲取這個可迭代對象的值,就能推動函數的執行,獲取新的返回值。直到函數執行結束。
-
生成器有什么好處呢?就是不會一下子在內存中生成太多數據
def genrator_fun1():a=1yield ab=2yield bg=genrator_fun1()
print(next(g))
print(next(g))
#生成器監聽文件輸入的例子
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
轉載于:https://www.cnblogs.com/so-cool/p/8916225.html
總結
以上是生活随笔為你收集整理的Python中的装饰器,迭代器,生成器的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。