迭代器
定义
python
里面迭代器指的是遵循迭代器协议的对象。迭代器协议指要实现对象的__iter()__
和__next__()
(python3)的方法,其中,__iter()__
方法返回迭代器对象本身,__next__()
方法返回容器的下一个元素,在没有后续元素会抛出StopIteration
异常。
注意一点的是python
里面的list
,set
,dict
并不是迭代器,它们是可迭代对象,但是它们并不是迭代器。一个实现了iter
方法的对象是可迭代的,一个实现了next
方法并且可迭代的对象时迭代器。这个在一次技术讨论中,我误以为list
等可迭代对象为迭代器,这是不对的。
什么是迭代?迭代指的是用循环(for
或者while
等)遍历容器中的元素的过程;什么是可迭代对象?可迭代对象指的是能够用for
循环进行迭代的对象,含有__iter__
和__next__
方法的对象成为可迭代对象。
例子
实现斐波那契数列迭代器:
from collections import Iterator
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
# 返回迭代器对象本身
def __iter__(self):
return self
# 返回容器下一个元素
def next(self):
self.a, self.b = self.b, self.a + self.b
return self.a
def main():
fib = Fib() # fib 是一个迭代器
print 'isinstance(fib, Iterator): ', isinstance(fib, Iterator)
for i in fib:
if i > 10:
break
print i
if __name__ == '__main__':
main()
优势
迭代器与列表的区别在于,构建迭代器的时候不像列表把所有元素一次性加载到内存,而是以一种延迟计算方式返回元素。在加载大数据的时候使用迭代器更有优势。
生成器
定义
生成器是一种特殊的迭代器,可以被用作控制循环的迭代行为,使用yield
返回值函数。每次调用yield
会暂停,而可以使用next()
函数和send()
函数恢复生成器。生成器类似于返回值数组的一个函数,这个函数可以接受参数,可以被调用。不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗内存数量将大大减少,而且允许调用函数可以很快处理前几个返回值,因此生成器看起来像个函数,但是表现得像迭代器。
注意: 生成器只能遍历一次。
生成器函数
常规函数定义,使用yield
语句返回结果。yield
语句一次返回一个结果,在每个结果中间,挂起一个函数的状态,以便下次在它离开的地方继续执行。
生成器表达式
类似于列表推导,但是生长期返回按需产生结果的一个对象,而不是全部结果的列表
装饰器
定义
装饰器是Python的一个重要部分。装饰器是修改其它函数的功能的函数,能够有助于使得代码更简短,也更加Pythonic
。
以下例子是一个简单的装饰器:
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()")
return wrapTheFunction
def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")
a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()
a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()
真正应用中的装饰器的写法:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return("Function is running")
can_run = True
print(func())
# Output: Function is running
can_run = False
print(func())
# Output: Function will not run
注意:@wraps
接受一个函数来进行修饰,并加入了复制函数名称、注释文档、参数列表等功能。
应用场景
授权
授权的应用可以参考我的github上的Flask-HTTPAuth。
日志
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
# Output: addition_func was called
带参数的装饰器
在函数中嵌入装饰器
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
@logit(logfile='func2.log')
def myfunc2():
pass
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
装饰器类
from functools import wraps
class logit(object):
def __init__(self, logfile='out.log'):
self.logfile = logfile
def __call__(self, func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile并写入
with open(self.logfile, 'a') as opened_file:
# 现在将日志打到指定的文件
opened_file.write(log_string + '\n')
# 现在,发送一个通知
self.notify()
return func(*args, **kwargs)
return wrapped_function
def notify(self):
# logit只打日志,不做别的
pass
调用:
@logit()
def myfunc1():
pass
参考
itertools
库的学习地址:https://pymotw.com/2/itertools/itertools
库的官网地址:https://docs.python.org/2/library/itertools.html