装饰器函数 迭代器函数 生成器函数

装饰器函数

装饰器的主要功能:在不改变函数调用方式的基础上在函数的前、后添加功能。

装饰器的固定格式:

#装饰器定式
#例子1:
def wrapper(func):
def inner(*args,**kargs):
ret = func(*args,**kargs)
return ret
return inner

@wrapper #语法糖 可用代替 qqxing =wrapper(qqxing)
def qqxing():
print(123)
ret = qqxing() #相当于执行inner
-----------------------------------------------------------
#例子2:
import time
def wrapper(func):         #装饰器函数,f是被装饰的函数
def inner(*args,**kwargs):
#在被装饰函数之前要做的事
ret = func(*args,**kwargs) #被装饰的函数
#在被装饰函数之后要做的事
return ret
return inner
@wrapper #语法糖
def func(a,b):
time.sleep(0.01)
print("你好",a,b)
func("小黑","小白")

带参数的装饰器


#假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?
# 一个一个的取消掉? 没日没夜忙活3天。。。
# 过两天你领导想通了,再让你加上。。。

#方法一:
#适用少量装饰器,每次需要更改每一个语法糖后面的变量值,比较麻烦。第二种是进阶方法
def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''执行函数之前要做的''')
            re = func(*args,**kwargs)
            if flag:
                print('''执行函数之后要做的''')
            return re
        return inner
    return timer

@outer(False)        #在语法糖后面加一个布尔值,当需要执行装饰器内部的函数就写成True,否则False
def func():
    print(111)
func()
-------------------------------------------------------------------
#方法二:
#是第一种方法的进阶版,只需要更改FLAG变量就可以控制所有的装饰器是否执行,适用于写了很多的装饰器
import time
FLAG=False         #只需要改变FLAG的变量 
def outer(flag):
def timmer(func):
def inner(*args,**kwargs):
if flag:
start = time.time()
ret =func(*args,**kwargs)
end=time.time()-start
print(end)
return ret
else:
ret =func(*args,**kwargs)
return ret
return inner
return timmer

@outer(FLAG)
def ceshi():
time.sleep(0.2)
print('测试成功')
ceshi()

@outer(FLAG)
def ceshi2():
time.sleep(0.3)
print('测试成功')
ceshi2()

 多个装饰器装饰同一个函数

def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner

def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner

@wrapper2
@wrapper1
def f():
    print('in f')
f()

#结果:

wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func

执行过程:

 

迭代器函数 

可迭代与迭代器的区别

可迭代:在Python中如果一个对象有__iter__( )方法或__getitem__( )方法,则称这个对象是可迭代的(Iterable);其中__iter__( )方法的作用是让对象可以用for ... in循环遍历,__getitem__( )方法是让对象可以通过“实例名[index]”的方式访问实例中的元素。换句话说,两个条件只要满足一条,就可以说对象是可迭代的。显然列表List、元组Tuple、字典Dictionary、字符串String等数据类型都是可迭代的。当然因为Python的“鸭子类型”,我们自定义的类中只要实现了__iter__( )方法或__getitem__( )方法,也是可迭代的

迭代器:在Python中如果一个对象有__iter__( )方法和__next__( )方法,则称这个对象是迭代器(Iterator);其中__iter__( )方法是让对象可以用for ... in循环遍历,__next__( )方法是让对象可以通过next(实例名)访问下一个元素。注意:这两个方法必须同时具备,才能称之为迭代器。列表List、元组Tuple、字典Dictionary、字符串String等数据类型虽然是可迭代的,但都不是迭代器,因为他们都没有next( )方法。

生成器函数 

#只含有yeild关键字的函数是生成器函数
#yeild不能和return共用且需要写在函数内部
def generate():
print(1)
yield 'a'
#生成器函数:执行之后会得到一个生成器作为返回值
g=generate() #g就是生成器
print(g)
ret=g.__next__()
print(ret)

#结果:
<generator object generate at 0x037F1F70>
1
a
#生产两百万件衣服
def closes():
    for i in range(200):
        yield'close%s'%i
g=closes()
for i in range(20):
    ret=g.__next__()
    print(ret)
for i in range(20):
    ret = g.__next__()
    print(ret)

 生成器函数进阶:

def generate():
    print(123)
    content=yield
    print('====',content)
    print(456)
    yield 2

g=generate()
ret=g.__next__()
print(ret)
ret = g.send('hello')      #send获取下一个值的效果和next效果一致                #只是在获取下一个值的时候,给上一个yield的位置传递一个数据
print(ret) 

#结果:
123
None
==== hello
456
2

#使用send的注意事项:
  #第一个使用生成器的时候,是用next获取下一个值
  #最后一个yield不能接受外部的值
#获取移动平均值
def average():
    sum=0
    count=0
    avg=0
    while True:
        num=yield avg
        sum =sum+num
        count=count+1
        avg=sum/count

生成器表达式和列表推导式

egg_list=[]                #for循环
for i in  range(10):
    egg_list.append("鸡蛋%s"%i)
print(egg_list)

egg_list=['鸡蛋%s'%i for i in range(10)]#列表推导式
print(egg_list)
#生成器表达式
g=(i for i in range(10))
print(g)
for i in g:
    print(i)

g=(i*i for i in range(10))
print(g)
for i in g:
    print(i)

#[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
#[满足条件的元素相关的操作 for 元素 in 可迭代的数据类型 if 元素相关的条件 ] #筛选功能 #30以内所有能被3整除的数 ret
=[i for i in range(30) if i%3==0] print(ret) #30以内所有能被3整除的数的平方 ret=[i*i for i in range(30) if i%3==0] print(ret) #找出嵌套列表中名字含有两个'e'的所有名字 names =[['hhhh','rrr','hhhh','eettr','tryee'],['sfsgg','eerfgsg','gertfre','atarw','sarar']] ret=[name for lst in names for name in lst if name.count('e')==2] print(ret)

面试题:

#面试题
def add(n,i):
    return n+i

def test():
    for i in range(4):
        yield i

g=test()
for n in [1,10]:
    g=(add(n,i) for i in g)

n=1
g = (add(n, i) for i in g)
n=10
g = (add(n, i) for i in (add(n, i) for i in g))
print(list(g))
原文地址:https://www.cnblogs.com/yzcstart/p/10580844.html