python装饰器[1]

首先先明白以下两点

#嵌套函数

defout1():definner1():print(1234)

inner1()#当没有加入inner时out()不会打印输出1234,当前层级也就是作用域下必须调用函数才能引用

out1()

#函数作用域

defout2():

a= 'aaa'

definner2():

a= 'bbb'

print(a)

inner2()print(a)

out2()#当相同变量处于不同嵌套函数中,会根据作用函数由内而外查找

装饰器:本质还是一个函数, 在不改变函数调用方式的情况下 对函数进行额外功能的封装,装饰一个函数 转给他一个其他的功能

装饰器的目的:装饰器的原本是用来在项目上线之后,因为已经上线了,大批量改代码的话很麻烦,由此产生了装饰器

不能修改被装饰的函数的源代码

不能修改被装饰的函数的调用方式

importtimedefdemo():print("wo shi rainbol")deftime1():

start=time.time()

demo()#给time1函数增加了一个demo的功能

end =time.time()print(end-start)

time1()#这样方式很low,如果有一个添加n个函数添加此功能会很麻烦

importtimedefdemo():print("wo shi rainbol")defdemo2():print("wo yeshi rainbol")deftime1(fuc):

start=time.time()

fuc()#把之前的demo改成公用的fuc,函数即变量

end =time.time()print(end-start)

time1(demo)#通过调用time1方法,fuc赋值成了demo,再调用demo的方法

time1(demo2)#time1(demo。。)

以上完成了对任意函数改变调用方式进行了功能的封装,那如何用不改变调用方式的情况下对其进行功能的封装呢?

importtimedefdemo():print("wo shi rainbol")deftime1(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方法

#下面通过真正的装饰器可以省去上面的步骤

importtimedeftime1(fuc):#2.time1(demo),这里的fuc相当于形参,其实就是demo

definner():

start=time.time()

fuc()

end=time.time()print(end-start)returninner#3.返回inner函数,但没有执行哦

@time1#1.python先会整体浏览一遍代码关键字的代码,找到了demo方法上头有装饰

# 先调用装饰器,time1也就是demo = time1(demo),括号中的demo相当于实参

defdemo():print("wo shi rainbol")

# demo = time1(demo) <=====> @time1 去掉@time1在这家这段也是一样的

demo()#4.现在才执行()执行函数

#简单装饰器

importtimedefsimper(fuc):def inner(*args,**kwargs):

start=time.time()

fuc(*args,**kwargs)#增加的方法

end =time.time()print(end -start)returninner

@simper#demo = simper(demo)

def demo(name):#定义一个方法

print(name)#增加一个公用的功能点

demo(1)

#高级装饰器  当我们再原来装饰器的业务上再增加一个形参,来判断我们的业务是否符合指定的状态,这需要外面再套一层函数

importtimedefharder(type):if type == 1:defout(fuc):def inner(*args,**kwargs):

start=time.time()

fuc(*args,**kwargs)

end=time.time()print(end -start)returninnerreturnoutelif type == 2:pass@harder(1)#返回out函数

defdemo(name):print(name)

demo(1)

python装饰器[2]

装饰器与之间的迭代

下面是产品四次提出需求后再不修改调用参数使用装饰器在修改lose函数来完成我们业务上的需求,原因是上线项目许多接口都调用我们这个类下的参数,再不破坏接口本身情况下使用装饰器迭代是最佳选择

importtime#现在有一个需求1.0:在整个功能的基础上再添加一个减去4.5的操作使得最后结果为0,前提条件是不修改调用参数

defouter(fuc):def inner(*args, **kwargs):

a= fuc(*args, **kwargs) - 4.5

returnareturninner#迭代需求1.1:在整个功能的基础上再添加一个增加10的操作使得最后结果为10,提前条件是不修改调用参数

defouter2(fuc2):def inner2(*args, **kwargs):

b= fuc2(*args, **kwargs) + 10

returnint(b)returninner2#迭代需求1.2:在整个功能的基础上再添加一个时间参数判断lose函数的时间,目前为了模拟添加2秒延迟时间,提前条件是不修改调用参数

defshowtime(fuc):def inner3(*args, **kwargs):

starttime=time.time()

a= fuc(*args, **kwargs)

time.sleep(2)

endtime=time.time()

b= endtime -starttimereturna, breturninner3#迭代需求2.0:目前项目的lose的方法在业务繁忙时会异常中断,为此接口添加异常处理,提前条件是不修改调用参数

deftryexception(fuc):def tryer(self, *args, **kwargs):try:

res= fuc(self, *args, **kwargs)exceptException as e:

self.lose()return 'ERROR'

returnresreturntryer

'''主程序'''classMyDecorato(object):def __init__(self):pass

defchengxu(self, a, b):

c= a +breturnc

@tryexception#4.最后调用tryexception装饰器,装饰器之间调用是从下到上来依次调用

@showtime #3.调用showtime装饰器

@outer2 #2.调用outer2装饰器

@outer #1.先调用outer装饰器

deflose(self, c):#频繁调用的函数lose

pingjun= c / 2

returnpingjun

d=MyDecorato()

res1= d.chengxu(6, 3)

res2, time=d.lose(res1)print('最后的值:', res2, '时间:', time)

python装饰器[3]

#wrap函数为functools标准库中模块

deftest():'''i am test'''

print('一个简单的实验')

test()print(test.__doc__)print(test.__name__)#

#>> 一个简单的实验#>> i am test#>> test

print('--------------------------------')defouter(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')returninner

@outerdeftest():'''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里面的数据就要调用一个特定装饰器来帮我们实现

importfunctoolsdefouter(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

@outerdeftest():'''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的属性值一样,这样也可以实现同样的效果

importfunctoolsdefouter(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__

returninner

@outerdeftest():'''i am test'''

print('一个简单的实验')

test()print(test.__doc__)print(test.__name__)

python装饰器[4]

#通过类中的装饰器实现,普通方式

classFoo(object):def __init__(self):pass

defdecorator(foo):definner(self):print('before')

foo(self)print('after')returninner

@decoratordeftest(self):print('testing')

foo=Foo()

foo.test()

#通过类中的装饰器实现,继承方式

classFoo(object):def __init__(self):pass

defdecorator(self):def inner(*args, **kwargs):print('before')

self(*args, **kwargs)print('after')returninner

@decoratordeftest1(self):print('我被执行了')classFoo2(Foo):

@Foo.decorator#执行被继承的方法

defdecorator(self):print('执行被继承的方法开始')

super(Foo2, self).test1()#运行Foo2父类Foo的test1方法

print('执行被继承的方法结束')

foo=Foo()

foo.test1()print('-----')

foo2=Foo2()

foo2.decorator()

#实例

classTest1(object):defdecorator1(self):def inner(*args, **kwargs):

self(*args, **kwargs)print('n年前添加的附加功能')returninner

@decorator1deftest1(self):print('n年前实现的某个功能')classTest2(Test1):defdecorator2(self):def inner(*args, **kwargs):

self(*args, **kwargs)print('今天添加的附加功能')returninner

@decorator2deftest2(self):

super(Test2, self).test1()print('昨天自己实现的功能')

foo=Test2()

foo.test2()

View Code

#通过类中的装饰器实现,获取对象方法的实例属性defmod_test(cls):#返回修改的类

defdecorator(fun):#返回装饰函数

defnew_fun(self):print(self.before)print(fun(self))print(self.after)returnnew_fun

cls.test=decorator(cls.test)returncls

@mod_testclassFoo(object):def __init__(self):

self.before= "before"self.after= "after"

deftest(self):return "testing"foo=Foo()

foo.test()

python迭代器

l = [1,2,3,4,5,6]print(l.__iter__()) #iter(l)这两者是一样的,都返回了一样迭代器对象

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 importIterator,Iterable#Iterable 迭代器#Iterator 迭代对象

print(isinstance([1334],list))#判断给对象是否为一个list,返回布尔值

print(isinstance(l,Iterable))#判断是否是迭代对象,返回布尔值

自定义迭代器

classMytest:def __init__(self, len):

self.index=0

self.len=lendef __iter__(self):returnselfdef __next__(self):if self.index

self.index+= 1

returnself.indexraiseStopIterationfor i in Mytest(20):print(i)#打印1-20,迭代器底层调用,结构复杂

python生成器

用法1:

f = (x for x in range(1000))#使用列表生成式外面套了一层中括号并赋值给f对象

print(f)#此时f打印的就是一个生成器对象 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

deftest(len):print(len,'11')yield 1

print(len,'222')yield 2

print(len,'333')

test('1')#此函数不会被调用

for i in test('1'):#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))

协程

简单的说只要能够完成多任务切换的都是协程,规避io操作是协程体现出的效果

yield是协程最底层的使用方法

#yield的使用

deff():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 importgreenletdeftest1():print('111')

b.switch()print('333')

b.switch()deftest2():print('222')

a.switch()print('444')

a= greenlet(test1)#创建一个生成器对象

b =greenlet(test2)

a.switch()

#from gevent import monkey#monkey.patch_all()#实时监听io堵塞,效果显著,要注意的是这两句话要放到最上面不然就会报错,我也不知道为什么

importgeventdeftest3():print('模拟io堵塞1')

gevent.sleep(1)#模拟堵塞时间

print('堵塞消除1')deftest4():print('模拟io堵塞2')

gevent.sleep(2)print( '堵塞消除2')

gevent.joinall([gevent.spawn(test3),gevent.spawn(test4)])#joinall效果是如果两个方法中其中一个出现io堵塞,会跳到另外一个方法,如果都堵塞都会等着,直到io堵塞消除#优势:io堵塞的时间取决于io堵塞最长的时间,提升效率

协程实例:

from gevent importmonkey

monkey.patch_all()

#gevent模块  #基于greenlet封装,避免多线程切换导致io执行效率降低

importgeventimportrequestsdefrun(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 inurl.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的装饰器、迭代器、yield_python装饰器,迭代器,生成器,协程相关推荐

  1. Python 中的黑暗角落(二):生成器协程的调度问题

    前作介绍了 Python 中的 yield 关键字.此篇介绍如何使用 yield 表达式,在 Python 中实现一个最基本的协程调度示例,避免 I/O 操作占用大量 CPU 计算时间. 协程及其特点 ...

  2. Python进阶(5)_进程与线程之协程、I/O模型

    三.协程 3.1协程概念 协程:又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存 ...

  3. python获取get请求的耗时时间_突破python爬取极限,超牛逼的异步协程爬虫

    异步协程 1. event_loop 2. coroutine 中文翻译叫协程,在 Python 中昌指代为协程对象类型,可以将协程对象注册到时间循环中被调用.使用 async 关键字来定义的方法在调 ...

  4. python并发编程之多进程、多线程、异步和协程

    转载 自 tyomcat: https://www.cnblogs.com/tyomcat/p/5486827.html 一.多线程 多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活 ...

  5. python多核cpu_Python中的多核CPU共享数据之协程详解

    一 : 科普一分钟 尽管进程间是独立存在的,不能相互访问彼此的数据,但是在python中却存在进程间的通信方法,来帮助我们可以利用多核CPU也能共享数据. 对于多线程其实也是存在一些缺点的,不是任何场 ...

  6. Python高并发爬虫测评(2): 多进程, 多线程和异步协程哪个快?

    在Python爬虫下一代网络请求库httpx和parsel解析库测评一文中我们对比了requests的同步爬虫和httpx的异步协程爬虫爬取链家二手房信息所花的时间(如下所示:一共580条记录),结果 ...

  7. python 异步 async/await -1.一文理解什么是协程

    前言 Python 在 3.5 版本中引入了关于协程的语法糖 async 和 await, 在 python3.7 版本可以通过 asyncio.run() 运行一个协程. 所以建议大家学习协程的时候 ...

  8. Python gevent高并发(限制最大并发数、协程池)

    实例源码 import time import gevent from gevent.pool import Pool from gevent import monkey monkey.patch_a ...

  9. python模拟多线程http请求_用python实现自己的http服务器——多进程、多线程、协程、单进程非堵塞版、epoll版...

    了解http协议 http请求头 GET / HTTP/1.1 Host: www.baidu.com Connection: keep-alive Pragma: no-cache Cache-Co ...

最新文章

  1. Extmail配置实践(一)
  2. 微软雅黑的应用[补充中]
  3. SAP 电商云 Spartacus UI 客户端模式下从服务器端渲染模式接收到的状态转移
  4. [PAT乙级]1043 输出PATest
  5. Java中文与ASCII码的转换
  6. mysql查询1971年以前_mysql查询昨天 一周前 一月前 一年前的数据
  7. python进阶19垃圾回收GC
  8. Mysql经常使用函数汇总
  9. 深入学习c++--智能指针(二) weak_ptr(打破shared_ptr循环引用)
  10. 前端开发学习要装哪些电脑软件
  11. (附源码)springboot投票系统的开发毕业设计261136
  12. OpenWRT设置SmartDNS+ADGuardHome
  13. h5学习笔记 左右布局
  14. RHCE linux学习第一天
  15. Java300集零基础自学
  16. java图片轮播_轮播图制作
  17. 【STM8L】Active-Halt模式下的低功耗
  18. pip永久修改下载源(豆瓣源)
  19. C语言十进制转八进制
  20. 05_Java筑基之Java开发初体验

热门文章

  1. 【视频版】最新版Swagger 3升级指南和新功能体验!
  2. WinRAR(WinZip)压缩与解压实现(C#版Window平台)
  3. 转载:JAVA获取时间戳,哪个更快
  4. 按钮button加超链接
  5. 手把手带你玩转Tensorflow 物体检测 API (2)——数据准备
  6. servlet+JQuery ajax以json的形式的验证表单小实例
  7. 彻底理解 Cookie、Session、Token
  8. 转自知乎-我见过最通俗易懂的KMP算法详解
  9. win10创建新的计算机用户名和密码错误,Win10开机提示用户名或密码不正确现象的解决办法...
  10. medoo update mysql_Medoo Update的使用:修改更新数据