Py学习  »  Python

在Python代码中,您在哪里使用生成器特性?

systempuntoout • 6 年前 • 1732 次点击  

我已经学习了生成器特性,我想我已经掌握了它,但是我想知道在哪里可以将它应用到我的代码中。

我在“python-essential-reference”一书中读到了以下示例:

# tail -f
 def tail(f):
  f.seek(0,2) 
  while True:
   line = f.readline() 
   if not line: 
     time.sleep(0.1)
     continue
   yield line

你有没有其他有效的例子,发电机是最好的工具,如tail-f?

您多久使用一次生成器功能,以及通常在程序的哪种功能\部分中应用它?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/38655
文章 [ 4 ]  |  最新文章 6 年前
Rafał Dowgird
Reply   •   1 楼
Rafał Dowgird    15 年前

一般来说,将数据获取(可能很复杂)与消费分开。特别地:

  • 要连接多个B树查询的结果,db部分将生成并执行查询 yield -通过记录,消费者只看到单个数据项到达。
  • 缓冲(预读)-生成器获取块中的数据,并从每个块生成单个元素。同样,消费者与血淋淋的细节是分开的。

发电机也可以作为协同工作。你可以传递数据 进入之内 他们使用 nextval=g.next(data) 在“消费者”方面, data = yield(nextval) 在发电机侧。在这种情况下,发电机及其用户的“交换”值。你甚至可以 产量 在生成器上下文中引发异常: g.throw(exc) 就是这样。

S.Lott
Reply   •   2 楼
S.Lott    15 年前

在所有情况下,我都有读任何东西的算法,我只使用生成器。

为什么?

在多个生成器的上下文中,在过滤、映射和约简规则中进行分层要容易得多。

例子:

def discard_blank( source ):
    for line in source:
        if len(line) == 0:
            continue
        yield line

def clean_end( source ):
    for line in source:
        yield line.rstrip()

def split_fields( source ):
    for line in source;
        yield line.split()

def convert_pos( tuple_source, position ):
    for line in tuple_source:
        yield line[:position]+int(line[position])+line[position+1:]

with open('somefile','r') as source:
    data= convert_pos( split_fields( discard_blank( clean_end( source ) ) ), 0 )
    total= 0
    for l in data:
        print l
        total += l[0]
    print total

我的偏好是使用许多小的生成器,这样一个小的更改就不会破坏整个流程链。

Felix Kling
Reply   •   3 楼
Felix Kling    15 年前

每当您的代码生成 值的数量不受限制 或者更一般地说,如果 内存太多 首先会被生成整个列表所消耗。

或者如果你 不要 迭代 完整生成的列表 (而且名单很大)。我的意思是,如果没有使用每个值,就没有必要先生成它(并等待生成)。

我最近遇到的生成器是当我实现一个线性循环序列(LRS)时,比如斐波那契序列。

Nick Dandoulakis
Reply   •   4 楼
Nick Dandoulakis    15 年前

当我实现扫描器(标记化器)或在数据容器上迭代时,我经常使用它们。

编辑:这是一个用于C++语法高亮程序的演示记录器:

whitespace = ' \t\r\n'
operators = '~!%^&*()-+=[]{};:\'"/?.,<>\\|'

def scan(s):
    "returns a token and a state/token id"
    words = {0:'', 1:'', 2:''} # normal, operator, whitespace
    state = 2 # I pick ws as first state
    for c in s:
        if c in operators:
            if state != 1:
                yield (words[state], state)
                words[state] = ''
            state = 1
            words[state] += c
        elif c in whitespace:
            if state != 2:
                yield (words[state], state)
                words[state] = ''
            state = 2
            words[state] += c
        else:
            if state != 0:
                yield (words[state], state)
                words[state] = ''
            state = 0
            words[state] += c
    yield (words[state], state)

用法示例:

>>> it = scan('foo(); i++')
>>> it.next()
('', 2)
>>> it.next()
('foo', 0)
>>> it.next()
('();', 1)
>>> it.next()
(' ', 2)
>>> it.next()
('i', 0)
>>> it.next()
('++', 1)
>>>