博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python中的装饰器,迭代器,生成器
阅读量:6202 次
发布时间:2019-06-21

本文共 5382 字,大约阅读时间需要 17 分钟。

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  ret    return inner   #实际上是把函数名字传递给timmer,timmer执行,之所以返回inner是因为inner在全局不可以被调用@timmerdef fun1(num):    print("in func1 {}".format(num))    return 123# print(timmer(fun1))    #可以运行,其实就是执行Inner,目的就是在全局可以调用,# fun1=timmer(fun1)      #函数本身就是变量,变量值互换print(fun1(1))
  • 这样可以修饰多个函数,但是要批量更改该怎么,如果不想装饰了,需要挨个去掉吗

import timedef outer():    Flag=False    def 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 ret            else:                ret = fun(*args, **kwargs)                return ret        return inner   #实际上是把函数名字传递给timmer,timmer执行,之所以返回inner是因为inner在全局不可以被调用    return timmer   @outer()           #之所以加执行就是把outer的返回值timmer函数的内存地址放在这里,其实就是@timmerdef 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=True    def 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 ret                    user_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"]=name                        login_status["status"]=True                        print(login_status)                        ret = func(*args,**kwargs)                        return  ret                    else:                        print("bad")            else:                ret = func(*args, **kwargs)                return ret        return inner    return 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@wrapper1def f():    print('in f')f()

  结果原因如下:从后分析

 装饰器小练习:

#编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果import timefrom 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 ret    return inner@wrapperdef 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]))
  • 用__next__也可以遍历,不依赖for循环

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..try..

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=1    yield a    b=2    yield bg=genrator_fun1()print(next(g))print(next(g))#生成器监听文件输入的例子

  

  

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

  

转载于:https://www.cnblogs.com/so-cool/p/8916225.html

你可能感兴趣的文章
github常用命令
查看>>
request模块
查看>>
I/O流之FileWriter【获取当前目录下所有子文件的绝对路径】
查看>>
435. Non-overlapping Intervals
查看>>
221. Maximal Square
查看>>
图片校验码
查看>>
20145237实验三
查看>>
2017-2018-1 20145237《信息安全系统设计基础》第二周考试
查看>>
RocketMQ顺序消息
查看>>
code::blocks10.05让C代码使用C99标准
查看>>
[转]如何处理海量数据
查看>>
自己的养生计划
查看>>
[POI2000]病毒
查看>>
Java + Excel 接口自动化
查看>>
Centos7开机自动启动服务和联网
查看>>
find()
查看>>
HTML5元素
查看>>
模仿spring authentication-provider 自己写登录人管理
查看>>
[转载]持续交付和DevOps的前世今生
查看>>
初始编码
查看>>