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

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

装饰器

高级函数

1函数名和变量名一样,只是一个变量标识符,它指向函数定义对应的内容存地址。
2 函数定义中存在调用其他函数,并不会立刻调用该函数
3 在执行一个调用了其他函数的函数时候,在内存中没有找到被调用函数的定义,会报错。(如下代码示例)

def foo():
    print('in foo')
    boo()
foo()
def boo():
    print('in boo') 

装饰器

定义:用来装饰其他函数,即为其他函数添加特定功能的函数。输出输出都为单一函数
装饰器基本原则:
1、装饰器不能修改被装饰函数源码;
2、装饰器不能修改被装饰函数的调用方式;
代码示例

import time
def timer(timer_type):
    print(timer_type)
    def outer(func):
        def inner(*args, **kwargs):
            time_start = time.time()
            res = func(*args, **kwargs)
            time_end = time.time()
            print("运行时间:",timer_type, time_end - time_start)
            return res
        return inner
    return outer
    
@timer(timer_type='minites') #等同于foo=timer(timer_type='minites')(foo)
def foo(name, age):
    time.sleep(3)
    print('in foo', name, age)
    return name

print(foo('xx',11))

说明:通过内嵌函数定义一个函数,把原函数包装上,返回新函数。
详细见:
Python进阶教学——装饰器与闭包
python函数(5)— 可变参数 *args 和 **kwargs

闭包

用来在一个函数与一组私有变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保证持久性。
在这里插入图片描述
装饰器和闭包对比:

装饰器闭包
装饰器外层主要是提供被装饰函数的引用。如foo=timer(timer_type=‘minites’)(foo)闭包外层主要是提供自有变量
装饰器外层函数不一定提供变量闭包外层函数必须提供变量,否则无意义
装饰器目的:为被装饰函数提供额外功能闭包目的:为函数保存运行环境和局部变量

迭代器

可迭代对象:只要定义了一个可返回迭代器的__iter__方法,或者定义了__getitem__方法,就是一个可迭代对象。
判断是否可以迭代:

print(hasattr([],'__getitem__'))
print(hasattr([],'__iter__'))

getitem:根据传入的int参数,返回一个列表中的元素
iter:返回一个可迭代对象
next:当被迭代时,返回下一个迭代的对象

class Empolyee:
    def __init__(self,names):
        self.names = names
    def __getitem__(self,item):
        return self.names[item] 

empolyee = Empolyee(['a','b'])
for i in empolyee: print(i)

迭代器:实现了__next__方法和__iter__方法(缺一不可)的对象。__iter__方法返回迭代器自身,__next__方法返回迭代器的下一值,直到没有元素,会抛出StopIteration异常(for循环会自动处理StopIteration异常)
迭代器一定是可迭代对象,可迭代对象不一定是迭代器。迭代器可以每次调用的使用生成迭代元素,而不是提前准备好所有的迭代元素,从而大大降低内存消耗。

from itertools import count
counter = count(start=10)  #count没有len方法,可以一直迭代下去
print(type(counter))
print(dir(counter))
print(next(counter))

可以通过iter方法把一个可迭代对象变为迭代器(补全__next__方法和__iter__方法),同时也会去掉包括len,append,add,reverse,copy等方法

my_list = [1,2,3]
my_list_iter = iter(my_list)
print(set(dir(my_list_iter))-set(dir(my_list)))
print(set(dir(my_list))-set(dir(my_list_iter)))
print(type(my_list_iter))
print(next(my_list_iter))

打印结果:

{'__next__', '__setstate__', '__length_hint__'}
{'remove', '__imul__', '__rmul__', 'clear', '__class_getitem__', '__mul__', '__getitem__', 'sort', 'append', 'index', '__len__', 'pop', '__contains__', '__add__', 'extend', '__setitem__', '__iadd__', 'reverse', 'copy', '__reversed__', '__delitem__', 'insert', 'count'}
<class 'list_iterator'>

生成器

生成器是一种特殊的迭代器,不需要显式写__next__方法和__iter__方法,只需要yield关键字。
yield作用
1、程序每次迭代中遇到yield, 会返回结果;
2、保留函数当前运行状态,等下一次调用,会从上一次返回yield语句处开始执行后面语句。
3、预激活机制,生成器在没有调用next方法之前,是不执行的
4、可以通过send方法,从调用放往生成器中传入参数。send会和next一样,会调用一次生成器,到下一次yield,同时给生成器传递参数。
5、throw,如果throw(StopIteration)代表跳过中间数值,结束生成器。自定义异常(ValueError和TypeError),抛出后执行返回下一个值
6、手动结束迭代器可以使用g.close() ,结束迭代器后g.next()会报错。

def count_down(n):
    print("count down from {}".format(n))
    while n > 0:
        new_value = yield n
        if new_value is not None:
            n = new_value
        else:
            n -= 1
c = count_down(10)  #预激活
for x in c:
    print(x)
    if x == 10:
        print(c.send(3))

结果:

count down from 10
10
3
2
1

raise exception in generator,return next yielded value or StopIteration,即在生成器中抛出异常,并且这个throw函数会返回下一个要迭代的值或者是StopIteration。

def my_generator():
    while True:
        try:
            yield 'a'
            yield 'b'
            yield 'c'
            yield 'd'
            yield 'e'
        except ValueError:
            print('触发“ValueError"了')
        except TypeError:
            print('触发“TypeError"了')
 
g=my_generator()
print(next(g))
print(next(g))
print('-------------------------')
print(g.throw(ValueError))
print('-------------------------')
print(next(g))
print(next(g))
print('-------------------------')
print(g.throw(TypeError))
print('-------------------------')
print(next(g))
'''运行结果为:
a
b
-------------------------
触发“ValueError"了
a
-------------------------
b
c
-------------------------
触发“TypeError"了
a
-------------------------
b
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值