python装饰器,迭代器,生成器,协程
python装饰器[1]
首先先明白以下两点
- #嵌套函数
- def out1():
- def inner1():
- print(1234)
- inner1()#当没有加入inner时out()不会打印输出1234,当前层级也就是作用域下必须调用函数才能引用
- out1()
- #函数作用域
- def out2():
- a = 'aaa'
- def inner2():
- a = 'bbb'
- print(a)
- inner2()
- print(a)
- out2()#当相同变量处于不同嵌套函数中,会根据作用函数由内而外查找
装饰器:本质还是一个函数, 在不改变函数调用方式的情况下 对函数进行额外功能的封装,装饰一个函数 转给他一个其他的功能
装饰器的目的:装饰器的原本是用来在项目上线之后,因为已经上线了,大批量改代码的话很麻烦,由此产生了装饰器
- 不能修改被装饰的函数的源代码
- 不能修改被装饰的函数的调用方式
- import time
- def demo():
- print("wo shi rainbol")
- def time1():
- start = time.time()
- demo()#给time1函数增加了一个demo的功能
- end = time.time()
- print(end-start)
- time1()
- #这样方式很low,如果有一个添加n个函数添加此功能会很麻烦
- import time
- def demo():
- print("wo shi rainbol")
- def demo2():
- print("wo yeshi rainbol")
- def time1(fuc):
- start = time.time()
- fuc()#把之前的demo改成公用的fuc,函数即变量
- end = time.time()
- print(end-start)
- time1(demo)#通过调用time1方法,fuc赋值成了demo,再调用demo的方法
- time1(demo2)
- #time1(demo。。)
- 以上完成了对任意函数改变调用方式进行了功能的封装,那如何用不改变调用方式的情况下对其进行功能的封装呢?
- import time
- def demo():
- print("wo shi rainbol")
- def time1(fuc):
- def inner():#根据之前学过的嵌套函数,增加一层inner方法,把值放入其中
- start = time.time()
- fuc()
- end = time.time()
- print(end-start)
- return inner#返回inner方法,但是没有运行
- demo = time1(demo)#time1包含了inner的功能/拿到inner的返回值并且赋值给res,装饰器的目的是不改变变量名所以这边仍然用demo变量赋值
- demo()#demo通过括号运行inner方法
- #下面通过真正的装饰器可以省去上面的步骤
- import time
- def time1(fuc):#2.time1(demo),这里的fuc相当于形参,其实就是demo
- def inner():
start = time.time()
fuc()
end = time.time()
print(end-start)
return inner#3.返回inner函数,但没有执行哦
@time1 #1.python先会整体浏览一遍代码关键字的代码,找到了demo方法上头有装饰
# 先调用装饰器,time1也就是demo = time1(demo),括号中的demo相当于实参
- def demo():
- print("wo shi rainbol")
- # demo = time1(demo) <=====> @time1 去掉@time1在这家这段也是一样的
- demo()#4.现在才执行()执行函数
- #简单装饰器
- import time
- def simper(fuc):
- def inner(*args,**kwargs):
- start = time.time()
- fuc(*args,**kwargs)#增加的方法
- end = time.time()
- print(end - start)
- return inner
- @simper #demo = simper(demo)
- def demo(name):#定义一个方法
- print(name)#增加一个公用的功能点
- demo(1)
- #高级装饰器 当我们再原来装饰器的业务上再增加一个形参,来判断我们的业务是否符合指定的状态,这需要外面再套一层函数
- import time
- def harder(type):
- if type == 1:
- def out(fuc):
- def inner(*args,**kwargs):
- start = time.time()
- fuc(*args,**kwargs)
- end = time.time()
- print(end - start)
- return inner
- return out
- elif type == 2:
- pass
- @harder(1)#返回out函数
- def demo(name):
- print(name)
- demo(1)
其他可以参考https://blog.csdn.net/u013471155/article/details/68960244 这个写得很详细
python装饰器[2]
装饰器与之间的迭代
下面是产品四次提出需求后再不修改调用参数使用装饰器在修改lose函数来完成我们业务上的需求,原因是上线项目许多接口都调用我们这个类下的参数,再不破坏接口本身情况下使用装饰器迭代是最佳选择
- import time
- # 现在有一个需求1.0:在整个功能的基础上再添加一个减去4.5的操作使得最后结果为0,前提条件是不修改调用参数
- def outer(fuc):
- def inner(*args, **kwargs):
- a = fuc(*args, **kwargs) - 4.5
- return a
- return inner
- # 迭代需求1.1:在整个功能的基础上再添加一个增加10的操作使得最后结果为10,提前条件是不修改调用参数
- def outer2(fuc2):
- def inner2(*args, **kwargs):
- b = fuc2(*args, **kwargs) + 10
- return int(b)
- return inner2
- # 迭代需求1.2:在整个功能的基础上再添加一个时间参数判断lose函数的时间,目前为了模拟添加2秒延迟时间,提前条件是不修改调用参数
- def showtime(fuc):
- def inner3(*args, **kwargs):
- starttime = time.time()
- a = fuc(*args, **kwargs)
- time.sleep(2)
- endtime = time.time()
- b = endtime - starttime
- return a, b
- return inner3
- # 迭代需求2.0:目前项目的lose的方法在业务繁忙时会异常中断,为此接口添加异常处理,提前条件是不修改调用参数
- def tryexception(fuc):
- def tryer(self, *args, **kwargs):
- try:
- res = fuc(self, *args, **kwargs)
- except Exception as e:
- self.lose()
- return 'ERROR'
- return res
- return tryer
- '''主程序'''
- class MyDecorato(object):
- def __init__(self):
- pass
- def chengxu(self, a, b):
- c = a + b
- return c
- @tryexception #4.最后调用tryexception装饰器,装饰器之间调用是从下到上来依次调用
- @showtime # 3.调用showtime装饰器
- @outer2 # 2.调用outer2装饰器
- @outer # 1.先调用outer装饰器
- def lose(self, c):#频繁调用的函数lose
- pingjun = c / 2
- return pingjun
- d = MyDecorato()
- res1 = d.chengxu(6, 3)
- res2, time = d.lose(res1)
- print('最后的值:', res2, '时间:', time)
python装饰器[3]
- #wrap函数为functools标准库中模块
- def test():
- '''i am test'''
- print('一个简单的实验')
- test()
- print(test.__doc__)
- print(test.__name__)
- #
- #>> 一个简单的实验
- #>> i am test
- #>> test
- print('--------------------------------')
- def outer(fuc):
- '''outer is me'''
- print('this is outer')
- def inner(*args,**kwargs):
- '''inner is me'''
- print('this is inner1')
- fuc(*args,**kwargs)
- print('this is inner2')
- return inner
- @outer
- def test():
- '''i am test'''
- print('一个简单的实验')
- test()
- print(test.__doc__)
- print(test.__name__)
- #>> this is outer
- #>> this is inner1
- #>> 一个简单的实验
- #>> this is inner2
- #>> inner is me
- #>> inner
- print('-----------------------')
- #如果我们想要得到test里面的数据就要调用一个特定装饰器来帮我们实现
- import functools
- def outer(fuc):
- '''outer is me'''
- print('this is outer')
- # @functools.wraps(fuc)
- def inner(*args,**kwargs):
- '''inner is me'''
- print('this is inner1')
- fuc(*args,**kwargs)
- print('this is inner2')
- #return inner
- return functools.update_wrapper(inner,fuc)#@functools.wraps(fuc)也可以,update_wrapper是调用其内部wrapper
- @outer
- def test():
- '''i am test'''
- print('一个简单的实验')
- test()
- print(test.__doc__)
- print(test.__name__)
- #>> this is outer
- #>> this is inner1
- #>> 一个简单的实验
- #>> this is inner2
- #>>> i am test
- #>> test
- print('------------------')
- #保持wrapper和test的属性值一样,这样也可以实现同样的效果
- import functools
- def outer(fuc):
- '''outer is me'''
- print('this is outer')
- def inner(*args,**kwargs):
- '''inner is me'''
- print('this is inner1')
- fuc(*args,**kwargs)
- print('this is inner2')
- inner.__doc__ = fuc.__doc__
- inner.__name__ = fuc.__name__
- return inner
- @outer
- def test():
- '''i am test'''
- print('一个简单的实验')
- test()
- print(test.__doc__)
- print(test.__name__)
python装饰器[4]
- #通过类中的装饰器实现,普通方式
- class Foo(object):
- def __init__(self):
- pass
- def decorator(foo):
- def inner(self):
- print('before')
- foo(self)
- print('after')
- return inner
- @decorator
- def test(self):
- print('testing')
- foo = Foo()
- foo.test()
- #通过类中的装饰器实现,继承方式
- class Foo(object):
- def __init__(self):
- pass
- def decorator(self):
- def inner(*args, **kwargs):
- print('before')
- self(*args, **kwargs)
- print('after')
- return inner
- @decorator
- def test1(self):
- print('我被执行了')
- class Foo2(Foo):
- @Foo.decorator # 执行被继承的方法
- def decorator(self):
- print('执行被继承的方法开始')
- super(Foo2, self).test1() # 运行Foo2父类Foo的test1方法
- print('执行被继承的方法结束')
- foo = Foo()
- foo.test1()
- print('-----')
- foo2 = Foo2()
- foo2.decorator()
- #实例
- class Test1(object):
- def decorator1(self):
- def inner(*args, **kwargs):
- self(*args, **kwargs)
- print('n年前添加的附加功能')
- return inner
- @decorator1
- def test1(self):
- print('n年前实现的某个功能')
- class Test2(Test1):
- def decorator2(self):
- def inner(*args, **kwargs):
- self(*args, **kwargs)
- print('今天添加的附加功能')
- return inner
- @decorator2
- def test2(self):
- super(Test2, self).test1()
- print('昨天自己实现的功能')
- foo = Test2()
- foo.test2()
- #通过类中的装饰器实现,获取对象方法的实例属性
- def mod_test(cls):
- # 返回修改的类
- def decorator(fun):
- # 返回装饰函数
- def new_fun(self):
- print(self.before)
- print(fun(self))
- print(self.after)
- return new_fun
- cls.test = decorator(cls.test)
- return cls
- @mod_test
- class Foo(object):
- def __init__(self):
- self.before = "before"
- self.after = "after"
- def test(self):
- return "testing"
- foo = Foo()
- foo.test()
python迭代器
- l = [1,2,3,4,5,6]
- print(l.__iter__()) #iter(l) 这两者是一样的,都返回了一样迭代器对象 <list_iterator object at 0x00000000023B7080>
- d = (iter(l))
- print((next(d)))#返回 1
- print((next(d)))#返回 2
- #所以生成器本身就是迭代器
- #for循环本身主要做的三件事:
- for i in [1,2,34,5,5]:
- # 1.
- iter([1,2,34,5,5])#调用可迭代对象的iter方法返回一个迭代器对象
- # 2.调用迭代器对象的next方法
- # 3.处理Stoplteration
- #校验
- from collections import Iterator,Iterable
- # Iterable 迭代器
- # Iterator 迭代对象
- print(isinstance([1334],list))#判断给对象是否为一个list,返回布尔值
- print(isinstance(l,Iterable))#判断是否是迭代对象,返回布尔值
自定义迭代器
- class Mytest:
- def __init__(self, len):
- self.index = 0
- self.len = len
- def __iter__(self):
- return self
- def __next__(self):
- if self.index < self.len:
- self.index += 1
- return self.index
- raise StopIteration
- for i in Mytest(20):
- print(i)
- #打印1-20,迭代器底层调用,结构复杂
python生成器
用法1:
- f = (x for x in range(1000))#使用列表生成式外面套了一层中括号并赋值给f对象
- print(f)#此时f打印的就是一个生成器对象 <generator object <genexpr> at 0x0000000001DD79E8>
- #此时需要打印x必须如下方式,生成器就像一位厨师,做出x就是一盘盘菜,每一盘菜必须吃完再吃第二盘,而且不能跳着吃,倒着吃
- print(next(f))#调用使用next()比较常见
- print(next(f))
- print(next(f))
- print(f.__next__())#f.__next__()也是可以的 py2的调用方式是f.next直接调用
- print(f.__next__())
- print(f.__next__())
用法2:
- #yield也是生成器中的例子,如果在没有使用next(),函数根本不会被执行,调用每一次程序会检测yield如果有,yield包括后面的代码不会执行,直到下次调用才执行下次的,所以函数中只要有yield就是生成器
- #yield可以理解成return
- def test(len):
- print(len,'')
- yield 1
- print(len,'')
- yield 2
- print(len,'')
- test('')#此函数不会被调用
- for i in test(''):#for内置有生成器next,可以对生成器对象一直使用next(n)
- print(i,'调用')
- #打印
- # 1 11
- # 1 调用
- # 1 222
- # 2 调用
- # 1 333
- #这个就是异步io的原理了,python里面的协程基于yield实现
- #生成器的好处:
- #如果我们写一个 danger = [x for x in range(9999999999999999999)]
- # 当我们打印danger时我们的电脑会在内存中放置0-n的数据,造成内存不足,死机的情况,生成器的出现会把旧变量替换成新变量,从而不会造成大数据所产成内存泄露的问题
- nodanger = (x for x in range(999999999999999999999999))
- print(next(nodanger))
协程
yield是协程最底层的使用方法
- #yield的使用
- def f():
- print('jjjj')
- yield 1
- print('gggg')
- yield
- print(f())#创建一个生成器对象,但是函数不会执行
- gen = f()
- #next(gen)#执行生成器对象
- gen.send(None)
- x = gen.send(10)#next(gen)这两者是一样的
- print(x)
gevent模块
- #gevent模块 在gevent中主要模式就是greenlet,它是c扩展的轻量级协程
- from greenlet import greenlet
- def test1():
- print('')
- b.switch()
- print('')
- b.switch()
- def test2():
- print('')
- a.switch()
- print('')
- a = greenlet(test1)#创建一个生成器对象
- b = greenlet(test2)
- a.switch()
- # from gevent import monkey
- # monkey.patch_all()#实时监听io堵塞,效果显著,要注意的是这两句话要放到最上面不然就会报错,我也不知道为什么
- import gevent
- def test3():
- print('模拟io堵塞1')
- gevent.sleep(1)#模拟堵塞时间
- print('堵塞消除1')
- def test4():
- print('模拟io堵塞2')
- gevent.sleep(2)
- print( '堵塞消除2')
- gevent.joinall([gevent.spawn(test3),gevent.spawn(test4)])
- #joinall效果是如果两个方法中其中一个出现io堵塞,会跳到另外一个方法,如果都堵塞都会等着,直到io堵塞消除
- #优势:io堵塞的时间取决于io堵塞最长的时间,提升效率
协程实例:
- from gevent import monkey
- monkey.patch_all()
- #gevent模块 #基于greenlet封装,避免多线程切换导致io执行效率降低
- import gevent
- import requests
- def run(name, url):
- r = requests.get(url)
- open(name + '.html', 'wb').write(r.content)
- url = {'rainbol01': 'https://www.cnblogs.com/RainBol/',
- 'rainbol02': 'https://www.cnblogs.com/RainBol/p/9505438.html',
- 'rainbol03': 'https://www.cnblogs.com/RainBol/p/10077388.html'
- }
- for name, url in url.items():
- g = gevent.spawn(run, name, url) # 启动
- g.join() # 等待并切换
- #阻塞等待分配任务完成后结束
- # l = []
- # for i in range(10):
- # g = gevent.spawn(run,name,url)
- # l = g.append(g)
- # g.joinall(l)
版权声明:本文原创发表于 博客园,作者为 RainBol本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
python装饰器,迭代器,生成器,协程的更多相关文章
- Python装饰器、生成器、内置函数、json
这周学习了装饰器和生成器,写下博客,记录一下装饰器和生成器相关的内容. 一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如 ...
- Python学习---装饰器/迭代器/生成器的学习【all】
Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210
- python笔记3 闭包 装饰器 迭代器 生成器 内置函数 初识递归 列表推导式 字典推导式
闭包 1, 闭包是嵌套在函数中的 2, 闭包是内层函数对外层函数的变量(非全局变量)的引用(改变) 3,闭包需要将其作为一个对象返回,而且必须逐层返回,直至最外层函数的返回值 闭包例子: def a1 ...
- python 装饰器,生成器,迭代器
装饰器 作用:当我们想要增强原来已有函数的功能,但不想(无法)修改原函数,可以使用装饰器解决 使用: 先写一个装饰器,就是一个函数,该函数接受一个函数作为参数,返回一个闭包,而且闭包中执行传递进来的函 ...
- Python中的装饰器,迭代器,生成器
1. 装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象. 强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式 装饰器的目标:在遵循1和2的 ...
- python 装饰器、生成器、迭代器
# 装饰器'''由高阶函数(把一个函数名当作实参传递给另一个函数,返回值中包含函数名)和嵌套函数(函数中嵌套函数)组成功能:在不更改原函数的代码和调用方式的前提下添加新的功能装饰器本身就是一个函数.使 ...
- python中的装饰器迭代器生成器
装饰器: 定义:本质是函数(装饰其它函数) 为其它函数添加附加功能 原则: 1 不能修改被装饰函数源代码 2 不修改被装饰函数调用方式 实现装饰器知识储备: 1 函数即‘’变量‘’ 2 高阶函数 ...
- Day4 装饰器——迭代器——生成器
一 装饰器 1.1 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多 ...
- day04 装饰器 迭代器&生成器 Json & pickle 数据序列化 内置函数
回顾下上次的内容 转码过程: 先decode 为 Unicode(万国码 ) 然后encode 成需要的格式 3.0 默认是Unicode 不是UTF-8 所以不需要指定 如果非要转为U ...
随机推荐
- kubernetes的几个概念
1. rc: 副本控制器,确保在任何时候都运行指定数量的pod副本.换句话说,ReplicationController确保一个pod或一组同构的pod始终处于可用状态. 2. rs:副本集,是rc ...
- JDBC(连接数据库的四个主要步骤)
JDBC连接数据库 ?创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...
- python基础篇(三)
PYTHON基础篇(三) 装饰器 A:初识装饰器 B:装饰器的原则 C:装饰器语法糖 D:装饰带参数函数的装饰器 E:装饰器的固定模式 装饰器的进阶 A:装饰器的wraps方法 B:带参数的装饰器 C ...
- webpack config to use plugin and webpack-dev-server
Demo3操作手册 本Demo演示如何配合各种plugin进行偏复杂的使用 准备环境 初始化环境, cd到demo1目录之后, 执行如下命令: npm init -y npm install webp ...
- From 虚拟机模板 创建单节点K8S1.14.1的操作步骤
半年前总结的 还是有记不住的地方... 1. 根据上一篇blog 自己创建了一个虚拟机 里面包含 k8s1.14.1 的k8s集群 这里简单说一下 虚拟机开机之后 如何处理以能够使用k8s 的简单过程 ...
- [itext]Java生成PDF文件
一.前言 最近在做也导出试卷的功能,刚开始是导出为doc,可是导出来格式都有变化,最后说直接将word转为pdf,可是各种不稳定,各种报错.最后想到直接将文件写入pdf(参考:http://www.c ...
- Java8新特性 - 并行流与串行流
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流. Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作.Stream API可以声明性地通过parallel()和 ...
- windows下搭建nginx负载均衡
学习笔记,第一次记录避免忘记 首先介绍一下本地环境是windows2008 R2-64位. 1. 到nginx官网上下载最新稳定版的安装包,http://nginx.org/en/download. ...
- 🕯国家公祭日-默哀javascript脚本
国行公祭,祀我国殇 兽行暴虐,共御外侮 昭昭前事,惕惕后人 永失弗谖,祈愿和平 var national_memorial_days=['12-13']; var dateObj=new Date() ...
- FaceBook CVPR2014: DeepFace解读
DeepFace是Facebook在2014年的CVPR上提出来的,后续出现的DeepID和FaceNet也都体现DeepFace的身影,可以说DeepFace是CNN在人脸识别的奠基之作,目前深 ...