python生成器实例,生成器详解
分类:面向对象

Python函数式编程指南(四):生成器详明,python编制程序指南

4. 生成器(generator)

4.1. 生成器简单介绍

第风姿罗曼蒂克请确信,生成器正是少年老成种迭代器。生成器具备next方法并且作为与迭代器完全相似,那意味着生成器也得以用来Python的for循环中。其它,对于生成器的极度语法协理使得编写贰个生成器比自定义一个平常的迭代器要简单不菲,所以生成器也是最常用到的特性之一。

从Python 2.5开始,[PEP 342:通过加强生成器落成协同程序]的落到实处为生成器参预了越来越多的风味,那意味着生成器还足以做到更加多的劳作。那部分大家会在稍后的生龙活虎部分介绍。

4.2. 生成器函数

4.2.1. 施用生成器函数定义生成器

怎么着得到一个生成器?首先来看一小段代码:
复制代码 代码如下:
>>> def get_0_1_2():
...   yield 0
...   yield 1
...   yield 2
...
>>> get_0_1_2
<function get_0_1_2 at 0x00B2CB70>

笔者们定义了一个函数get_0_1_2,而且能够查阅到那诚然是函数类型。但与平日的函数区别的是,get_0_1_2的函数体内使用了首要字yield,那使得get_0_1_2成为了二个生成器函数。生成器函数的表征如下:

1.调用生成器函数将赶回一个生成器;
复制代码 代码如下:
>>> generator = get_0_1_2()
>>> generator
<generator object get_0_1_2 at 0x00B1C7D8>

2.首先次调用生成器的next方法时,生成器才起来试行生成器函数(并非创设生成器时),直到碰到yield时停顿实施(挂起),何况yield的参数将用作此次next方法的再次回到值;
复制代码 代码如下:
>>> generator.next()
0

3.过后每一趟调用生成器的next方法,生成器将从上次打退堂鼓试行的职位恢复生机推行生成器函数,直到再也遭遇yield时停顿,並且相通的,yield的参数将用作next方法的再次来到值;
复制代码 代码如下:
>>> generator.next()
1
>>> generator.next()
2

4.万大器晚成当调用next方法时生成器函数甘休(境遇空的return语句或是到达函数体末尾),则此次next方法的调用将抛出StopIteration异常(即for循环的截止条件);
复制代码 代码如下:
>>> generator.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

5.生成器函数在每便暂停奉行时,函数体内的保有变量都将被保留(freezeState of Qatar在生成器中,并将要回复履行时回涨,并且雷同于闭包,即便是同八个生成器函数重临的生成器,封存的变量也是互为独立的。
大家的小例子中并未利用变量,所以这里此外定义一个生成器来浮现那天性情:
复制代码 代码如下:
>>> def fibonacci():
...   a = b = 1
...   yield a
...   yield b
...   while True:
...     a, b = b, a+b
...     yield b
...
>>> for num in fibonacci():
...   if num > 100: break
...   print num,
...
1 1 2 3 5 8 13 21 34 55 89

来看while True可别太吃惊,因为生成器能够挂起,所以是延迟总结的,Infiniti循环并从未涉嫌。这一个事例中大家定义了一个生成器用于获取斐波那契数列。

4.2.2. 生成器函数的FAQ
接下去大家来研商一些关于生成器的风趣的话题。

1.您的例证里生成器函数都未有参数,那么生成器函数能够带参数吗?

当然能够啊亲,并且它扶植函数的全部参数情势。要明了生成器函数也是函数的意气风发种:)
复制代码 代码如下:
>>> def counter(start=0):
...   while True:
...     yield start
...     start += 1
...

那是叁个从内定数开端的流量计。

2.既然生成器函数也是函数,那么它可以应用return输出再次回到值吗?

非常的亲,是如此的,生成器函数已经有私下认可的重回值——生成器了,你不可能再其它给三个重回值;对,尽管是return None也极度。可是它能够使用空的return语句结束。假若你坚威武不能屈要为它钦命再次回到值,那么Python将要概念的职责赠送四个语法错误至极,有如那样:
复制代码 代码如下:
>>> def i_wanna_return():
...   yield None
...   return None
...
  File "<stdin>", line 3
SyntaxError: 'return' with argument inside generator

3.好啊,那人家供给保险释放能源,须求在try...finally中yield,那会是神马情形?(笔者哪怕想玩你)小编在finally中还yield了贰次!
Python会在真的离开try...finally时再实行finally中的代码,而这里缺憾地告知您,暂停不算哦!所以结局你也能猜到吧!
复制代码 代码如下:
>>> def play_u():
...   try:
...     yield 1
...     yield 2
...     yield 3
...   finally:
...     yield 0
...
>>> for val in play_u(): print val,
...
1 2 3 0

*那与return的情事分裂。return是实在的相距代码块,所以会在return时即刻奉行finally子句。
*除此以外,“在含蓄finally子句的try块中yield”定义在PEP 34第22中学,那代表唯有Python 2.5之上版本才支撑那一个语法,在Python 2.4以下版本中会拿到语法错误非凡。

4.假设自己索要在生成器的迭代进度中连着另一个生成器的迭代如何是好?写成上边那样好傻好天真。。
复制代码 代码如下:
>>> def sub_generator():
...   yield 1
...   yield 2
...   for val in counter(10): yield val
...

这种意况的语法修正已经被定义在[PEP 380:委托至子生成器的语法]中,听新闻说会在Python 3.3中完毕,届期也大概回馈到2.x中。达成后,就足以如此写了:
复制代码 代码如下:
>>> def sub_generator():
...   yield 1
...   yield 2
...   yield from counter(10)
  File "<stdin>", line 4
    yield from counter(10)
             ^
SyntaxError: invalid syntax

总的来看语法错误木有?将来大家还是天真一点啊~

有越多难题?请回复此文:)

4.3. 协同程序(coroutineState of Qatar

协作程序(协程)日常的话是指那样的函数:

1.互相间有例外的局地变量、指令指针,但仍分享全局变量;
2.足以方便地挂起、苏醒,况兼有多少个入口点和出口点;
3.三个协作程序间显现为同盟运营,如A的运行进程中供给B的结果才干继续实施。

协程的特色决定了同等时刻只好有壹个协作程序正在运营(忽视八线程的景色)。得益于此,协程间能够一贯传送对象而无需思量财富锁、或是直接唤醒其余协程而没有须要主动休眠,就像内置了锁的线程。在相符协程特点的应用处景,使用协程无疑比使用线程要更有益。

从单向说,协程不能并发其实也将它的利用途景限定在了多少个很狭小的限量,那几个特点使得协程更加多的被拿来与常规函数实行对比,并不是与线程。当然,线程比协程复杂超多,成效也更加强盛,所以作者提出我们牢牢地通晓线程就可以:Python线程指南

那大器晚成节里小编也就不列举关于协程的事例了,以下介绍的艺术掌握就可以。

Python 2.5对生成器的抓牢落到实处了协程的别的特色,在此个本子中,生成器参预了之类方法:

1.send(value):

send是除next外另二个重理旧业生成器的不二诀窍。Python 2.5中,yield语句产生了yield表明式,那表示yield以往能够有四个值,而以此值正是在生成器的send方法被调用进而恢复实行时,调用send方法的参数。
复制代码 代码如下:
>>> def repeater():
...   n = 0
...   while True:
...     n = (yield n)
...
>>> r = repeater()
>>> r.next()
0
>>> r.send(10)
10

*调用send传入非None值前,生成器必须处于挂起状态,否则将抛出拾壹分。可是,未运行的生成器还能够应用None作为参数调用send。
*要是应用next苏醒生成器,yield表明式的值将是None。
2.close():
这么些方法用于关闭生成器。对关闭的生成器后再行调用next或send将抛出StopIteration格外。
3.throw(type, value=None, traceback=None):
以此艺术用于在生成器内部(生成器的一时挂起处,或未运行时在定义处)抛出一个足够。
*别为没见到协程的事例缺憾,协程最广泛的用途其实就是生成器。

4.4. 三个风趣的库:pipe
这风度翩翩节里自个儿要向各位简介pipe。pipe并非Python内置的库,要是你安装了easy_install,直接能够安装它,不然你须要本人下载它:

从而要介绍这几个库,是因为它向我们来得了大器晚成种很有新意的应用迭代器和生成器的艺术:流。pipe将可迭代的数目作为是流,相符于linux,pipe使用'|'传递数据流,何况定义了一琳琅满指标“流管理”函数用于选用并管理数据流,并最后再度输出数据流恐怕是将数据流总结获得三个结实。大家来看有的例子。

先是个,特别简单的,使用add求和:

复制代码 代码如下:
>>> from pipe import *
>>> range(5) | add
10

追求数和内需采纳到where,效用相通于内建函数filter,过滤出相符条件的因素:
复制代码 代码如下:
>>> range(5) | where(lambda x: x % 2 == 0) | add
6

还记得大家定义的斐波那契数列生成器吗?求出数列中具有小于10000的偶数和内需用到take_while,与itertools的同名函数有肖似的法力,截取成分直到条件不树立:
复制代码 代码如下:
>>> fib = fibonacci
>>> fib() | where(lambda x: x % 2 == 0)
...       | take_while(lambda x: x < 10000)
...       | add
3382

内需对成分接收有些函数能够行使select,成效相似于内建函数map;要求拿到一个列表,能够动用as_list:

复制代码 代码如下:
>>> fib() | select(lambda x: x ** 2) | take_while(lambda x: x < 100) | as_list
[1, 1, 4, 9, 25, 64]

pipe中还包罗了越来越多的流管理函数。你以致可以团结定义流管理函数,只供给定义叁个生成器函数并累积修饰器Pipe。如下概念了三个获得成分直到索引不相符条件的流管理函数:

复制代码 代码如下:
>>> @Pipe
... def take_while_idx(iterable, predicate):
...   for idx, x in enumerate(iterable):
...     if predicate(idx): yield x
...     else: return
...

动用那么些流管理函数获取fib的前十二个数字:

复制代码 代码如下:
>>> fib() | take_while_idx(lambda x: x < 10) | as_list
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

更多的函数就不在那介绍了,你能够查阅pipe的源文件,总共600行不到的公文之中有300行是文档,文书档案中包括了汪洋的身体力行。

pipe实现起来特别轻松,使用Pipe装饰器,将平常的生成器函数(大概再次回到迭代器的函数)代理在三个落到实处了__ror__主意的日常类实例上就可以,不过这种思路真的很有意思。

函数式编制程序指南全文到这里就总体收场了,希望那后生可畏多元小说能给你带给援救。希望我们都能看见有个别布局式编程之外的编制程序情势,况且能够熟识地在适宜之处接收:)

次日我会收拾三个目录放上来方便查看,并且列出一些供参照他事他说加以考查的稿子。可惜的是这个小说大概都以克罗地亚语的,请努力学习乌Crane语吗

  • -#

  1. 生成器(generator卡塔尔 4.1. 生成器简介首先请确信,生成器正是风流倜傥种迭代器。生成器拥...

Python中的生成器和yield详细介绍,python生成器yield

列表推导与生成器表明式

当大家创立了叁个列表的时候,就创建了一个能够迭代的对象:

复制代码 代码如下:

>>> squares=[n*n for n in range(3)]
>>> for i in squares:
 print i
 
0
1
4

这种成立列表的操作很普及,称为列表推导。不过像列表那样的迭代器,举个例子str、file等,尽管用起来很平价,但有一点点,它们是储存在内部存储器中的,倘若值相当的大,会很艰苦。

而生成器表明式不一样,它推行的乘除与列表包含相符,但会迭代的变化结果。它的语法与列表推导相似,只是要用小括号来代替中括号:

复制代码 代码如下:

>>> squares=(n*n for n in range(3))
>>> for i in squares:
 print i
 
0
1
4

生成器表明式不会成立系列情势的靶子,不会把全数的值都读取到内部存款和储蓄器中,而是会创立八个通过迭代并依据必要生成值的生成器对象(Generator卡塔尔。

那正是说,还应该有未有其它措施来产生生成器呢?

事例:斐波那契数列

诸如有个须要,要生成斐波那契数列的前十几人,大家得以如此写:

复制代码 代码如下:

def fib(n):
    result=[]
    a=1
    b=1
    result.append(a)
    for i in range(n-1):
        a,b=b,a+b
        result.append(a)
    return result
if __name__=='__main__':
    print fib(10)

数字少之甚少时,函数运行优越,但数字超级多时,难题就来了,显明生成多少个几千几万尺寸的列表并不是一个很好的意见。

那样,需要就改为了:写三个方可生成可迭代对象的函数,恐怕说,不要让函数三回回到全体的值,而是一遍回到贰个值。

那好像与大家的常识相违背,当我们调用一个味如鸡肋的Python函数时,平日是从函数的率先行代码早前实践,甘休于return语句、分外或然函数截止(能够用作隐式的回来None卡塔尔国:

复制代码 代码如下:

def fib(n):
    a=1
    b=1
    for i in range(n-1):
        a,b=b,a+b
        return a
if __name__=='__main__':
    print fib(10)
>>>
1    #回去第一个值时就卡住了

函数大器晚成旦将调控权交还给调用者,就意味着整个扫尾。函数中做的有所工作以致保存在局地变量中的数据都将错失。再一次调用这么些函数时,一切都将上马创制。函数唯有一回回到结果的机会,因此必需二次回到全体的结果。平日咱们都这么以为的。可是,假诺它们其实不然呢?请看奇妙的yield:

复制代码 代码如下:

def fib(n):
    a=1
    yield a
    b=1
    for i in range(n-1):
        a,b=b,a+b
        yield a
if __name__=='__main__':
    for i in fib(10):
        print i
>>>
1
1
2
3
5
8
13
21
34

生成器Generator

python中生成器的概念超级粗略,使用了yield关键字的函数就可以称呼生成器,它生成二个值的队列:

复制代码 代码如下:

def countdown(n):
    while n>0:
        yield n
        n-=1
if __name__=='__main__':
    for i in countdown(10):
        print i

生成器函数再次回到生成器。要注意的是生成器正是黄金年代类特殊的迭代器。作为四个迭代器,生成器必定要定义一些艺术,个中一个正是__next__(卡塔尔国。如同迭代器同样,大家得以接纳next(卡塔尔函数(Python3是__next__(State of Qatar卡塔尔国来获取下二个值:

复制代码 代码如下:

>>> c=countdown(10)
>>> c.next()
10
>>> c.next()
9

每当生成器被调用的时候,它会重返四个值给调用者。在生成器内部接受yield来产生那个动作。为了记住yield到底干了何等,最轻巧易行的方法是把它充当特意给生成器函数用的出格的return。调用next(卡塔尔时,生成器函数不断的执行语句,直至蒙受yield停止,当时生成器函数的”状态”会被冷冻,全数的变量的值会被保存下去,下黄金时代行要执行的代码之处也会被记录,直到再次调用next(卡塔尔继续施行yield之后的话语。

next(卡塔尔国不能够最佳施行,当迭代长逝时,会抛出StopIteration万分。迭代未告竣作时间,要是您想甘休生成器,可以运用close(卡塔尔方法。

复制代码 代码如下:

>>> c.next()
1
>>> c.next()
StopIteration
>>> c=countdown(10)
>>> c.next()
10
>>> c.close()
>>> c.next()
StopIteration

协程与yield表达式

yield语句还应该有更给力的效用,作为多少个言辞出以后赋值运算符的右侧,选用叁个值,或同期生成叁个值并收受八个值。

复制代码 代码如下:

def recv():
    print 'Ready'
    while True:
        n=yield
        print 'Go %s'%n
>>> c=recv()
>>> c.next()
Ready
>>> c.send(1)
Go 1
>>> c.send(2)
Go 2

以这种措施采纳yield语句的函数称为协程。在此个例子中,对于next(State of Qatar的初叶调用是少不了的,那样协程能力实行可通往第1个yield表达式的口舌。在这里地协程会挂起,等待有关生成器对象send(卡塔尔国方法给它发送多个值。传递给send(卡塔尔的值由协程中的yield表明式再次回到。

协程的运作日常是Infiniti制时间的,使用方法close(State of Qatar能够显式的闭馆它。

假使yield表明式中提供了值,协程能够接收yield语句同期收到和爆发重返值。

复制代码 代码如下:

def split_line():
    print 'ready to split'
    result=None
    while True:
        line=yield result
        result=line.split()
>>> s=split_line()
>>> s.next()
ready to split
>>> s.send('1 2 3')
['1', '2', '3']
>>> s.send('a b c')
['a', 'b', 'c']

注意:掌握那个例子中的前后相继顺序特别主要。第四个next(卡塔尔(قطر‎方法让协程施行到yield result,那将赶回result的值None。在接下去的send(卡塔尔(قطر‎调用中,选用到的值被内置line中并拆分到result中。send(卡塔尔方法的再次回到值便是下一条yield语句的值。也正是说,send(卡塔尔(قطر‎方法能够将叁个值传递给yield表明式,然而其重临值来自下二个yield表明式,并不是接收send(State of Qatar传递的值的yield表明式。

风流浪漫旦您想用send(卡塔尔(قطر‎方法来张开协程的实行,必需先send二个None值,因为那时是未曾yield语句来接收值的,不然就能够抛出非常。

复制代码 代码如下:

>>> s=split_line()
>>> s.send('1 2 3')
TypeError: can't send non-None value to a just-started generator
>>> s=split_line()
>>> s.send(None)
ready to split

选拔生成器与协程

乍看之下,如何利用生成器和协程解决实际难题仿佛并不理解。但在消除系统、网络和遍及式总结方面包车型客车一些难点时,生成器和协程极其有用。实际上,yield已经化为Python最强盛的最主要字之风流倜傥。

譬喻,要创制一个拍卖公事的管道:

复制代码 代码如下:

import os,sys
def default_next(func):
    def start(*args,**kwargs):
        f=func(*args,**kwargs)
        f.next()
        return f
    return start
@default_next
def find_files(target):
    topdir=yield
    while True:
        for path,dirname,filelist in os.walk(topdir):
            for filename in filelist:
                target.send(os.path.join(path,filename))

@default_next
def opener(target):
    while True:
        name=yield
        f=open(name)
        target.send(f)
   
@default_next
def catch(target):
    while True:
        f=yield
        for line in f:
            target.send(line)
           
@default_next
def printer():
    while True:
        line=yield
        print line

然后将那些协程连接起来,就足以创建三个数据流处理管道了:

复制代码 代码如下:

finder=find_files(opener(catch(printer())))
finder.send(toppath)

前后相继的实行完全由将数据发送到第叁个体协会程find_files(卡塔尔国中来驱动,协程管道会永世保持活动状态,直到它显式的调用close(卡塔尔。

简单的说,生成器的功能十二分苍劲。协程能够用于落到实处某种情势的面世。在一些类型的应用程序中,可以用几个职务调整器和有些生成器或协程完毕合营式顾客空间十二线程,即greenlet。yield的威力将要协程,协作式多职责管理(cooperative multitasking卡塔尔,以致异步IO中赢得真正的反映。

列表推导与生成器表明式 当大家创设了一个列表的时候,就创办了一个能够迭代的靶子:...

兵器谱

Python的迭代器和生成器使用实例,python生成器实例

一、迭代器Iterators

迭代器仅是风姿罗曼蒂克容器目的,它实现了迭代器合同。它有五个着力方法:

1)next方法
归来容器的下一个要素

2)__iter__方法
回到迭代器本人

迭代器可应用内建的iter方法创制,见例子:

复制代码 代码如下:

>>> i = iter('abc')
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
>>> i.next()
Traceback (most recent call last):
  File "<string>", line 1, in <string>
StopIteration:

class MyIterator(object):
  def __init__(self, step):
  self.step = step
  def next(self):
  """Returns the next element."""
  if self.step==0:
  raise StopIteration
  self.step-=1
  return self.step
  def __iter__(self):
  """Returns the iterator itself."""
  return self
for el in MyIterator(4):

if

  print el

结果:

复制代码 代码如下:

3
2
1
0

二、生成器Generators

从Python2.2起,生成器提供了意气风发种轻易的主意帮忙回去列表成分的函数来成功轻巧和实用的代码。
它基于yield指令,允许截止函数并当即赶回结果。

此函数保存其实施上下文,若是须求,可登时继续试行。

例如Fibonacci函数:

复制代码 代码如下:

def fibonacci():
  a,b=0,1
  while True:
  yield b
  a,b = b, a+b
fib=fibonacci()
print fib.next()
print fib.next()
print fib.next()

python未有三目运算符,笔者挺烦闷的,举例把七个整数不小的要命复制给三个变量,有三目运算符的言语会那样写:

print [fib.next() for i in range(10)]

结果:

复制代码 代码如下:

1
1
2
[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

PEP Python Enhancement Proposal Python巩固建议

tokenize模块

复制代码 代码如下:

>>> import tokenize
>>> reader = open('c:/temp/py1.py').next
>>> tokens=tokenize.generate_tokens(reader)
>>> tokens.next()
(1, 'class', (1, 0), (1, 5), 'class MyIterator(object):/n')
>>> tokens.next()
(1, 'MyIterator', (1, 6), (1, 16), 'class MyIterator(object):/n')
>>> tokens.next()
(51, '(', (1, 16), (1, 17), 'class MyIterator(object):/n')

例子:

复制代码 代码如下:

def power(values):
  for value in values:
  print 'powering %s' %value
  yield value
def adder(values):
  for value in values:
  print 'adding to %s' %value
  if value%2==0:
  yield value+3
  else:
  yield value+2
elements = [1,4,7,9,12,19]
res = adder(power(elements))
print res.next()

a = 1b = 2c = a > b ? a : b

print res.next()

结果:

复制代码 代码如下:

powering 1
adding to 1
3
powering 4
adding to 4
7

保持代码轻松,并不是数量。
静心:宁可有雅量简洁明了的可迭代函数,也不要三个头眼昏花的二次只总结出一个值的函数。

例子:

复制代码 代码如下:

def psychologist():
  print 'Please tell me your problems'
  while True:
  answer = (yield)
  if answer is not None:
  if answer.endswith('?'):
  print ("Don't ask yourself too much questions")
  elif 'good' in answer:
  print "A that's good, go on"
  elif 'bad' in answer:
  print "Don't be so negative"
free = psychologist()
print free.next()
print free.send('I feel bad')
print free.send("Why I shouldn't ?")

新生开掘Python的if语句可以写成生龙活虎行完毕上述意义:

print free.send("ok then i should find what is good for me")

结果:

复制代码 代码如下:

Please tell me your problems
None
Don't be so negative
None
Don't ask yourself too much questions
None
A that's good, go on
None

风姿浪漫、迭代器Iterators 迭代器仅是风流倜傥容器指标,它达成了迭代器合同。它有三个大旨措施:...

c = a if a > b else b

with

大家普通以如下情势操作文件:

try: f = open('/path/to/file', 'r')

print f.read()

finally:

if f:

f.close()

老是那样写太繁琐,来试试看with的威力:

with open('/path/to/file', 'r') as f:

print f.read()

代码更佳简洁,并且不必调用f.close(State of Qatar方法。

with利用了上下文物管理理契约,那东西聊起来太复杂,直接上代码。

自定义三个支持上下文管理左券的类, 类中实现enter方法和exit方法。

class MyWith(object):

def __enter__(self):

print "Enter with"

return self  # 重临对象给as后的变量

def __exit__(self, exc_type, exc_value, exc_traceback):

#闭馆财富等

if exc_traceback is None:           print "Exited without Exception"

return True

else:           print "Exited with Exception"

return Falsedef test_with():

with MyWith() as my_with:       print "running my_with"

print "------分割线-----"

with MyWith() as my_with:       print "running before Exception"

raise Exception       print "running after Exception"if __name__ == '__main__':

test_with()

输出:

Enter withrunning my_withExited without Exception------分割线-----Enter withrunning before ExceptionExited with Exception

map

大多数的for循环能够用map来代替,用法是:map(func,seq卡塔尔国,对seq中的每种成分举办操作,具体哪些操作在func里定义。

咱俩原先是那般写for循环的:

array = [1, 2, 3]

square_array = []for i in array:

square_array.append(i ** 2)

改用map:

array = [1, 2, 3]

square_array = map(lambda i: i ** 2, array)

map的首先个参数是lambda表明式,冒号前边的i作为形参,来自于array中的成分,冒号前边正是要赶回的值。

当然你也能够应用列表推导式来替代:

array = [1, 2, 3]

square_array = [i ** 2 for i in array]

filter

用法与map相同:filter(func,seq卡塔尔,对seq中的成分进行过滤,再次回到适合条件的那一个成分。

比方说再次回到array = [1, 2, 3, 4]中的全数奇数:

print filter(lambda i: i % 2, array)

这里是对2取余,再次来到结果为True的成分。那么什么样情状下结果为True?Python里面不为0,None只怕null都以True。所以结果就是,偶数是False,奇数是True,重临全体奇数。

列表推导式方案:

print [i for i in array if i % 2 != 0]

reduce

用法:reduce(func,seqState of Qatar,对seq中的每一个成分进行func操作,最终汇总再次回到三个值。

其三个参数0是count的最初值。

求array = [1, 2, 3]富有因素的和:

print reduce(lambda x, y: x + y, array)

reduce会先将array里面包车型地铁头多个数分别作为x和y,求它们的和,然后把它的结果和第八个相加,再把结果和第多个相加,直到尾数要素。

求array = [1, 2, 3]中的最大值:

print reduce(lambda x, y: x if x > y else y, array)

求strings = ["abc", "abcd", "def"]中"abc"出现的总次数:

print reduce(lambda count, str: count + str.count("abc"), strings, 0)

eval

实行叁个字符串表达式,并再次回到表明式的值。

print eval("1 + 1")

>> 2

再来个复杂点的:

def init():

return 1def func(num):

return 2action = {"num": init, "func": func}

expression = 'func(num)'print eval(expression, action)

>> 2

看不懂固然了,那玩意写起来很自然,不过杀敌大器晚成千,自损三百。

装饰器

设计格局的中的装饰器格局还记得呢,能够动态扩张二个类的作用,可是又不会校正那些类的源码,Java IO包多量用到了装饰器格局,大家来拜谒Python是怎么玩的。

举个简易的例子吗,在一个函数推行前打日志:

def log(func):

def wrapper(*args, **kwargs):

print('call %s()' % func.__name__)        return func(*args, **kwargs)    return wrapper@logdef func():

print 'do something'func()

输出:

call func()do something

生成器

yield是Python大旨关键字,不懂生成器,基本上就是把Python当坚实版的Shell在用。

迭代是在前后相继开拓中常用的操作,对一个列表进行遍历。然则倘使列表数据过多,譬如有上亿条,就能够越过标题,因为内存空间有限。生成器应时而生,举个斐波那契数列的例子:

def fib(n):

a = b = 1

for i in range(n):        yield a

a, b = b, a + bfor i in fib(10):    print i,

输出:

1 1 2 3 5 8 13 21 34 55

同盟send、next函数,生成器可以完毕协程的效益:

def func():

while True:

n = yield

print n

gen = func()print gen.next()

gen.send(2)

gen.send(3)

输出:

None23

调用next函数后,代码实施到yield,因为后边未有其余值,所以打字与印刷出来的结果是None,那个时候期码hold住,让出CPU。调用send(2State of Qatar后代码恢复生机试行,将2赋给n然后打字与印刷,yield自带next函数成效,代码继续实践到yield,生生不息。通过生成器在单线程的意况下完结了职责调整。

for/else

我们常常使用for循环来搜寻元素,有八个情景会使循环停下来:

要素被找到,触发break。

循环截止。

只是大家并不知道是哪位原因促成循环甘休,平时是设置三个标记,成分被找到,纠正标志的值。for/else可以异常高贵地化解那些标题:

for i in range(10):if i > 10:    print ielse:    print("can't find result")

你的主见再精粹,那是大费周折的价值

而你的价值,长久体以后行动之中

假定还停留在想的价值中,请及早行动,

例如您学习还截至在原处,请咨询小编扶植您从头

本文由10bet手机官网发布于面向对象,转载请注明出处:python生成器实例,生成器详解

上一篇:Validate设置onkeyup验证的实例代码,validate插件实现ajax验证重复的2种方法 下一篇:model遇到的问题
猜你喜欢
热门排行
精彩图文