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()#当相同变量处于不同嵌套函数中,会根据作用函数由内而外查找

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

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

  1. 不能修改被装饰的函数的源代码
  2. 不能修改被装饰的函数的调用方式
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装饰器,迭代器,生成器,协程的更多相关文章

  1. Python装饰器、生成器、内置函数、json

    这周学习了装饰器和生成器,写下博客,记录一下装饰器和生成器相关的内容. 一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如 ...

  2. Python学习---装饰器/迭代器/生成器的学习【all】

    Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210

  3. python笔记3 闭包 装饰器 迭代器 生成器 内置函数 初识递归 列表推导式 字典推导式

    闭包 1, 闭包是嵌套在函数中的 2, 闭包是内层函数对外层函数的变量(非全局变量)的引用(改变) 3,闭包需要将其作为一个对象返回,而且必须逐层返回,直至最外层函数的返回值 闭包例子: def a1 ...

  4. python 装饰器,生成器,迭代器

    装饰器 作用:当我们想要增强原来已有函数的功能,但不想(无法)修改原函数,可以使用装饰器解决 使用: 先写一个装饰器,就是一个函数,该函数接受一个函数作为参数,返回一个闭包,而且闭包中执行传递进来的函 ...

  5. Python中的装饰器,迭代器,生成器

    1. 装饰器 装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象. 强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式 装饰器的目标:在遵循1和2的 ...

  6. python 装饰器、生成器、迭代器

    # 装饰器'''由高阶函数(把一个函数名当作实参传递给另一个函数,返回值中包含函数名)和嵌套函数(函数中嵌套函数)组成功能:在不更改原函数的代码和调用方式的前提下添加新的功能装饰器本身就是一个函数.使 ...

  7. python中的装饰器迭代器生成器

    装饰器: 定义:本质是函数(装饰其它函数) 为其它函数添加附加功能 原则: 1 不能修改被装饰函数源代码    2 不修改被装饰函数调用方式 实现装饰器知识储备: 1 函数即‘’变量‘’ 2 高阶函数 ...

  8. Day4 装饰器——迭代器——生成器

    一 装饰器 1.1 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多 ...

  9. day04 装饰器 迭代器&生成器 Json & pickle 数据序列化 内置函数

    回顾下上次的内容 转码过程: 先decode  为 Unicode(万国码 ) 然后encode 成需要的格式     3.0 默认是Unicode  不是UTF-8 所以不需要指定  如果非要转为U ...

随机推荐

  1. java设计模式(一)——单例模式

    1.基本介绍 单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供-一个取得其对象实例的方法(静态方法).如:一般情况下,数据库的连接 2.创建方式: ...

  2. PHP中NULL和‘'的区别

    PHP中NULL和‘'区别 null的类型是null,""的类型是string 所以是不同东西 <pre>$a=22;unset($a);var_dump($a);&l ...

  3. Qt qml的软件架构设计

    google: qt qml application architecture 有很多资源. 1 https://www.ics.com/blog/multilayered-architecture- ...

  4. CF731E Funny Game

    题目描述 一个长度为 N 的序列 ai ,双方轮流操作 每次的操作是选择一个长度大于 1 的前缀,计算它的和 s ,然后 用 s 替换它的前缀,同时当前玩家获得 s 的分数. 当只剩下一个元素,游戏结 ...

  5. jquery中filter()和find()函数区别

    通常把这两个函数,filter()函数和find()函数称为筛选器. 下面的例子分别使用filter函数和find函数对一组列表进行筛选操作. 一组列表: <li>1</li> ...

  6. C++11(及现代C++风格)和快速迭代式开发

    过去的一年我在微软亚洲研究院做输入法,我们的产品叫“英库拼音输入法” (下载Beta版),如果你用过“英库词典”(现已更名为必应词典),应该知道“英库”这个名字(实际上我们的核心开发团队也有很大一部分 ...

  7. git 如何取消add操作

    可以直接使用命令    git reset HEAD 这个是整体回到上次一次操作 绿字变红字(撤销add) 如果是某个文件回滚到上一次操作:  git reset HEAD  文件名 红字变无 (撤销 ...

  8. 滤波器算法(1)-卡尔曼滤波小车附带题目与MATLAB程序

    1 简介 由卡尔曼这个学者提出的最佳线性滤波器,单纯时域维度即可实现[无需进行频域变换] 2 思路 由上一时刻的最佳估计值XKE_P预测①当前时刻预测值Pxv 与 ②当前时刻的测量值Mxv 进行联立计 ...

  9. Matlab匿名函数,向量化和预分配,函数的函数,P码文件

    匿名函数: 匿名函数是不存储在程序文件中.但与数据类型是 function_handle 的变量相关的函数.匿名函数可以接受输入并返回输出,就像标准函数一样.但是,它们可能只包含一个可执行语句. 例如 ...

  10. Spring/Spring Boot整合Weblogic JMS实战

    本文主要介绍weblogic jms的配置,包括JMS 服务器和JMS 模块(连接工厂.队列.远程 SAF 上下文.SAF 导入目的地.SAF 错误处理)的配置:并在Spring/Spring Boo ...