您的位置:首页 > 编程语言 > Python开发

Python菜鸟之路:Python基础-生成器和迭代器、递归

2016-06-17 00:02 585 查看

一、迭代器

  迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退。

1. 迭代器优点

  对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。本质:迭代器就是生成一个有next()方法的对象,而不是通过索引来计数。

  不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。这个特点被称为延迟计算或惰性求值(Lazy evaluation)。

  提供了一个统一的访问集合的接口,只要定义了__iter__()方法对象,就可以使用迭代器访问。

2. 两个基本的方法

  1) next方法:返回迭代器的下一个元素

a = {2,3,4,}
b = iter(a)
print(b.__next__())
print(b.__next__())
print(b.__next__())
print(b.__next__())

out:
2
3
4

Traceback (most recent call last):
File "practice3.py", line 216, in <module>
print(b.__next__())
StopIteration


# Ps:从上述例子可以看出,迭代器中元素被访问完毕,如果再次调用__next__方法,会提示StopIteration

  2) __iter__方法:返回迭代器对象本身

a = {2,3,4,}
b = iter(a)
print(b.__iter__())

out: <set_iterator object at 0x0000000000B377E0>


3. 迭代器的访问

  迭代器对象的访问方法,一般为for循环,循环取出可迭代对象中的元素。在for循环中,Python将自动调用函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。

  当然,也可以自己实现一个迭代器,如上所述,只需要在类的__iter__方法中返回一个对象,这个对象拥有一个next()方法,这个方法能在恰当的时候抛出StopIteration异常即可。其中,异常并不是非抛出不可的,不抛出该异常的迭代器将进行无限迭代,某些情况下这样的迭代器很有用。这种情况下,就需要自己判断元素并中止,否则就死循环了!

4. 迭代器的弊端

  使用迭代器的循环可以避开索引,这时候内建函数enumerate能在iter函数的结果前加上索引,以元组返回。之前的函数中已经见过这个內建函数的用法。

二、生成器

  带有 yield 的函数在 Python 中被称之为 generator,即生成器。

  简单地讲,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用函数并不会立即执行函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行函数内部的代码,执行到 yield 时,函数就返回一个迭代值,下次迭代时,代码从上次 yield 位置的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

1. 生成器的优点

  生成器是特定的函数,允许你返回一个值,然后“暂停”代码的执行,稍后恢复。生成器使用了“延迟计算”,所以在内存上面更加有效。

2. 生成一个如何判断一个生成器

def num():
a = 1
while a<=5:
yield a
a+=1
a = num()

from inspect import isgenerator
from inspect import isgeneratorfunction
# 判断对象是一个生成器
print(isgenerator(a))
out: True
# 判断函数是一个生成器函数
print(isgeneratorfunction(num))
out: True


3. 生成器利用案例

  文件读取:如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取

def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return


三、 相关库

  Python内置了一个模块itertools,包含了很多函数用于creating iterators for efficient looping(创建更有效率的循环迭代器)。该方法通常返回一个迭代器,可以通过for循环取值。

# encoding: utf-8
# module itertools
# from (built-in)
# by generator 1.138
"""
Functional tools for creating and using iterators.

Infinite iterators: #无限迭代
count(start=0, step=1) --> start, start+step, start+2*step, ...
#从start开始,以后每个元素都加上step。step默认值为1,count(10) --> 10 11 12 13 14 ...
cycle(p) --> p0, p1, ... plast, p0, p1, ...
#迭代至序列p的最后一个元素后,从p的第一个元素重新开始 cycle('ABCD') --> A B C D A B C D ...
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
#将elem重复n次。如果不指定n,则无限重复 repeat(10, 3) --> 10 10 10

Iterators terminating on the shortest input sequence: #在最短的序列参数终止时停止迭代
accumulate(p[, func]) --> p0, p0+p1, p0+p1+p2
#从第一个元素开始,依次累加,accumulate([1,2,3,4,5,6,7.....]) -->  1,3,6,10,15,21,28...
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...
#迭代至序列p的最后一个元素后,从q的第一个元素开始,直到所有序列终止 chain("ABC","BBC"):--> A B C B B C
chain.from_iterable([p, q, ...]) --> p0, p1, ... plast, q0, q1, ...
#迭代至序列p的最后一个元素后,从q的第一个元素开始,直到所有序列终止p,q都是可迭代对象,比如str: chain.from_iterable(["ABC","BBC"]) --> A B C B B C...
compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...
#如果bool(selectors
)为True,则next()返回data
,否则跳过data
。
dropwhile(pred, seq) --> seq
, seq[n+1], starting when pred fails
#当pred对seq
的调用返回False时才开始迭代 dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
#这个函数功能类似于SQL的分组。使用groupby前,首先需要使用相同的keyfunc对iterable进行排序,比如调用内建的sorted函数。然后,groupby返回迭代器,每次迭代的元素是元组(key值, iterable中具有相同key值的元素的集合的子迭代器) groupby([0, 0, 0, 1, 1, 1, 2, 2, 2]) --> (0, (0 0 0)) (1, (1 1 1)) (2, (2 2 2))
filterfalse(pred, seq) --> elements of seq where pred(elem) is False
#如果序列sql中的元素,带入函数pred[seq[0]]返回False,则返回序列中的这个值 filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
islice(seq, [start,] stop [, step]) --> elements from seq[start:stop:step]
#list(itertools.islice(range(100), 1, 10, 2)) --> [1, 3, 5, 7, 9]
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...
# 将seq的每个元素以变长参数(*args)的形式调用func, starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n
# 返回n个迭代器it的复制迭代器。
takewhile(pred, seq) --> seq[0], seq[1], until pred fails
# dropwhile的相反版本 takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...
#zip的取最长序列的版本,短序列将填入fillvalue。

Combinatoric generators:# 组合迭代器
product(p, q, ... [repeat=1]) --> cartesian product
# 笛卡尔积 print(list(itertools.product('ABC', repeat=2))) -> [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
permutations(p[, r])
# 去除重复的元素 print(list(itertools.permutations('ABC', 2)))-->[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
combinations(p, r)
# 排序后去重print(list(itertools.combinations('ABC', 2))) -> [('A', 'B'), ('A', 'C'), ('B', 'C')]
combinations_with_replacement(p, r)
# 排序后,包含重复元素 print(list(itertools.combinations_with_replacement('ABC', 2)))->[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
"""
# no imports

# functions

def tee(iterable, n=2): # real signature unknown; restored from __doc__
""" tee(iterable, n=2) --> tuple of n independent iterators. """
pass

# classes

class accumulate(object):
"""
accumulate(iterable[, func]) --> accumulate object

Return series of accumulated sums (or other binary function results).
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, func=None): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class chain(object):
"""
chain(*iterables) --> chain object

Return a chain object whose .__next__() method returns elements from the
first iterable until it is exhausted, then elements from the next
iterable, until all of the iterables are exhausted.
"""
@classmethod
def from_iterable(cls, iterable): # real signature unknown; restored from __doc__
"""
chain.from_iterable(iterable) --> chain object

Alternate chain() contructor taking a single iterable argument
that evaluates lazily.
"""
pass

def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, *iterables): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class combinations(object):
"""
combinations(iterable, r) --> combinations object

Return successive r-length combinations of elements in the iterable.

combinations(range(4), 3) --> (0,1,2), (0,1,3), (0,2,3), (1,2,3)
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, r): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

def __sizeof__(self, *args, **kwargs): # real signature unknown
""" Returns size in memory, in bytes. """
pass

class combinations_with_replacement(object):
"""
combinations_with_replacement(iterable, r) --> combinations_with_replacement object

Return successive r-length combinations of elements in the iterable
allowing individual elements to have successive repeats.
combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, r): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

def __sizeof__(self, *args, **kwargs): # real signature unknown
""" Returns size in memory, in bytes. """
pass

class compress(object):
"""
compress(data, selectors) --> iterator over selected data

Return data elements corresponding to true selector elements.
Forms a shorter iterator from selected data elements using the
selectors to choose the data elements.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, data, selectors): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

class count(object):
"""
count(start=0, step=1) --> count object

Return a count object whose .__next__() method returns consecutive values.
Equivalent to:

def count(firstval=0, step=1):
x = firstval
while 1:
yield x
x += step
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, start=0, step=1): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass

class cycle(object):
"""
cycle(iterable) --> cycle object

Return elements from the iterable until it is exhausted.
Then repeat the sequence indefinitely.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class dropwhile(object):
"""
dropwhile(predicate, iterable) --> dropwhile object

Drop items from the iterable while predicate(item) is true.
Afterwards, return every element until the iterable is exhausted.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, predicate, iterable): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class filterfalse(object):
"""
filterfalse(function or None, sequence) --> filterfalse object

Return those items of sequence for which function(item) is false.
If function is None, return the items that are false.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, function_or_None, sequence): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

class groupby(object):
"""
groupby(iterable[, keyfunc]) -> create an iterator which returns
(key, sub-iterator) grouped by each value of key(value).
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, key=None): # known case of itertools.groupby.__init__
""" Initialize self.  See help(type(self)) for accurate signature. """
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class islice(object):
"""
islice(iterable, stop) --> islice object
islice(iterable, start, stop[, step]) --> islice object

Return an iterator whose next() method returns selected values from an
iterable.  If start is specified, will skip all preceding elements;
otherwise, start defaults to zero.  Step defaults to one.  If
specified as another value, step determines how many values are
skipped between successive calls.  Works like a slice() on a list
but returns an iterator.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, stop): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class permutations(object):
"""
permutations(iterable[, r]) --> permutations object

Return successive r-length permutations of elements in the iterable.

permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iterable, r=None): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

def __sizeof__(self, *args, **kwargs): # real signature unknown
""" Returns size in memory, in bytes. """
pass

class product(object):
"""
product(*iterables, repeat=1) --> product object

Cartesian product of input iterables.  Equivalent to nested for-loops.

For example, product(A, B) returns the same as:  ((x,y) for x in A for y in B).
The leftmost iterators are in the outermost for-loop, so the output tuples
cycle in a manner similar to an odometer (with the rightmost element changing
on every iteration).

To compute the product of an iterable with itself, specify the number
of repetitions with the optional repeat keyword argument. For example,
product(A, repeat=4) means the same as product(A, A, A, A).

product('ab', range(3)) --> ('a',0) ('a',1) ('a',2) ('b',0) ('b',1) ('b',2)
product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) ...
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, *iterables, repeat=1): # known case of itertools.product.__init__
""" Initialize self.  See help(type(self)) for accurate signature. """
return []

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

def __sizeof__(self, *args, **kwargs): # real signature unknown
""" Returns size in memory, in bytes. """
pass

class repeat(object):
"""
repeat(object [,times]) -> create an iterator which returns the object
for the specified number of times.  If not specified, returns the object
endlessly.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, p_object, times=None): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

def __length_hint__(self, *args, **kwargs): # real signature unknown
""" Private method returning an estimate of len(list(it)). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __repr__(self, *args, **kwargs): # real signature unknown
""" Return repr(self). """
pass

class starmap(object):
"""
starmap(function, sequence) --> starmap object

Return an iterator whose values are returned from the function evaluated
with an argument tuple taken from the given sequence.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, function, sequence): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

class takewhile(object):
"""
takewhile(predicate, iterable) --> takewhile object

Return successive entries from an iterable as long as the
predicate evaluates to true for each entry.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, predicate, iterable): # real signature unknown; restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class zip_longest(object):
"""
zip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> zip_longest object

Return an zip_longest object whose .__next__() method returns a tuple where
the i-th element comes from the i-th iterable argument.  The .__next__()
method continues until the longest iterable in the argument sequence
is exhausted and then it raises StopIteration.  When the shorter iterables
are exhausted, the fillvalue is substituted in their place.  The fillvalue
defaults to None or can be specified by a keyword argument.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, iter1, iter2=None, *some, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class _grouper(object):
# no doc
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, *args, **kwargs): # real signature unknown
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

class _tee(object):
""" Iterator wrapped to make it copyable """
def __copy__(self, *args, **kwargs): # real signature unknown
""" Returns an independent iterator. """
pass

def __init__(self, *args, **kwargs): # real signature unknown
pass

def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

def __setstate__(self, *args, **kwargs): # real signature unknown
""" Set state information for unpickling. """
pass

class _tee_dataobject(object):
""" Data container common to multiple tee objects. """
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass

def __init__(self, *args, **kwargs): # real signature unknown
pass

@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object.  See help(type) for accurate signature. """
pass

def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass

class __loader__(object):
"""
Meta path import for built-in modules.

All methods are either class or static methods to avoid the need to
instantiate the class.
"""
@classmethod
def create_module(cls, *args, **kwargs): # real signature unknown
""" Create a built-in module """
pass

@classmethod
def exec_module(cls, *args, **kwargs): # real signature unknown
""" Exec a built-in module """
pass

@classmethod
def find_module(cls, *args, **kwargs): # real signature unknown
"""
Find the built-in module.

If 'path' is ever specified then the search is considered a failure.

This method is deprecated.  Use find_spec() instead.
"""
pass

@classmethod
def find_spec(cls, *args, **kwargs): # real signature unknown
pass

@classmethod
def get_code(cls, *args, **kwargs): # real signature unknown
""" Return None as built-in modules do not have code objects. """
pass

@classmethod
def get_source(cls, *args, **kwargs): # real signature unknown
""" Return None as built-in modules do not have source code. """
pass

@classmethod
def is_package(cls, *args, **kwargs): # real signature unknown
""" Return False as built-in modules are never packages. """
pass

@classmethod
def load_module(cls, *args, **kwargs): # real signature unknown
"""
Load the specified module into sys.modules and return it.

This method is deprecated.  Use loader.exec_module instead.
"""
pass

def module_repr(module): # reliably restored by inspect
"""
Return repr for the module.

The method is deprecated.  The import machinery does the job itself.
"""
pass

def __init__(self, *args, **kwargs): # real signature unknown
pass

__weakref__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
"""list of weak references to the object (if defined)"""

__dict__ = None # (!) real value is ''

# variables with complex values

__spec__ = None # (!) real value is ''


itertools.source

四、递归

1. 递归的概念

(1)递归就是在过程或函数里调用自身;
(2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

2. 可以解决的问题

(1)数据的定义是按递归定义的。(比如Fibonacci函数)
(2)问题解法按递归算法实现。(回溯)
(3)数据的结构形式是按递归定义的。(比如树的遍历,图的搜索)  

递归的优点:定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

递归的缺点:递归算法解题的运行效率较低。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等

3. 递归函数的创建

初始化算法。递归程序通常需要一个开始时使用的种子值(seed value)。要完成此任务,可以向函数传递参数,或者提供一个入口函数,这个函数是非递归的,但可以为递归计算设置种子值。

检查要处理的当前值是否已经与基线条件相匹配(base case)。如果匹配,则进行处理并返回值。

使用更小的或更简单的子问题(或多个子问题)来重新定义答案。

对子问题运行算法。

将结果合并入答案的表达式。

返回结果。

4. 递归函数的注意事项

  基线条件(base case)。基线条件是递归程序的最底层位置,在此位置时没有必要再进行操作,可以直接返回一个结果。所有递归函数都必须至少拥有一个基线条件,而且必须确保它们最终会达到某个基线条件;否则,程序将永远运行下去,直到程序缺少内存或者栈空间。因此,使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。下面看一个溢出的案例:

def fact(n):
if n==1:
return 1
return n * fact(n - 1)

fact(1000)
out:
RecursionError: maximum recursion depth exceeded in comparison


5. 解决递归栈溢出

  解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
  尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

6. 经典案例

  下面是一个未进行尾递归优化的递归函数

def fact(n):
if n==1:
return 1
return n * fact(n - 1)


  下面是进行了尾递归优化的函数(主要是要把每一步的乘积传入到递归函数中)

def fact(n):
return fact_iter(1, 1, n)

def fact_iter(product, count, max):
if count > max:
return product
return fact_iter(product * count, count + 1, max)


  可以看到,return fact_iter(product * count, count + 1, max)仅返回递归函数本身,product * count和count + 1在函数调用前就会被计算,不影响函数调用。

  尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
  遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。但是可以通过下面使用装饰器的方式来进行优化↓↓↓

7. 一个py3的尾递归优化的装饰器:

import sys

class TailRecurseException(BaseException):
def __init__(self, args, kwargs):
self.args = args
self.kwargs = kwargs

def tail_call_optimized(g):
"""
This function decorates a function with tail call
optimization. It does this by throwing an exception
if it is it's own grandparent, and catching such
exceptions to fake the tail call optimization.

This function fails if the decorated
function recurses in a non-tail context.
"""
def func(*args, **kwargs):
   # 获取当前栈信息
f = sys._getframe()
if f.f_back and f.f_back.f_back \
and f.f_back.f_back.f_code == f.f_code:
raise TailRecurseException(args, kwargs)
else:
while 1:
try:
return g(*args, **kwargs)
except TailRecurseException as e:
args = e.args
kwargs = e.kwargs
func.__doc__ = g.__doc__
return func

@tail_call_optimized
def factorial(n, acc=1):
"calculate a factorial"
if n == 0:
return acc
return factorial(n-1, n*acc)

print(factorial(1000))
out: 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
# prints a big, big number,
# but doesn't hit the recursion limit.

@tail_call_optimized
def fib(i, current = 0, next = 1):
if i == 0:
return current
else:
return fib(i - 1, next, current + next)

print(fib(1000))
out: 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: