如何从字符串产生字符

时间:2019-03-26 12:43:00

标签: python python-3.x recursion stack-overflow

我想拥有一个可调用的函数(因为iter()需要它),该函数可以为我提供字符串中的顺序字符。

此功能使我的电脑停滞了,我不得不重置计算机。

cnt=0
def myfunc():
    global cnt
    cnt+=1
    yield "abczdef"[cnt]

list(iter(myfunc,'z'))

2 个答案:

答案 0 :(得分:2)

您可以将字符串直接用作可迭代项:

def characters(string, sentinel):
    for c in string:
        if c == sentinel:
            break
        yield c
>>> list(characters('abczdef', 'z'))
['a', 'b', 'c']

一种更实用的方法,如您所想到的,将是:

from itertools import takewhile

def characters(string, sentinel):
    return takewhile(lambda c: c != sentinel, string))

也可以使用iter(callable, sentinel)表单,但是我发现其他解决方案更易读:

def characters(string, sentinel):
    chars = iter(string)
    return iter(lambda: next(chars), sentinel)

为什么您的尝试会冻结计算机

list(iter(myfunc,'z'))

等效于:

result = []
while True:
    x = myfunc()
    if x == 'z':
        break
    result.append(x)

如果您查看致电myfunc()时发生的情况:

>>> myfunc()
<generator object myfunc at 0x7f1e0f1020a0>
>>> myfunc()
<generator object myfunc at 0x7f1e0f1020f8>
>>> myfunc()
<generator object myfunc at 0x7f1e0f1020a0>

您看到每次调用它都会创建一个新的生成器对象。

很明显,这些对象都不等于'z',因此会产生无限循环。

答案 1 :(得分:0)

使用语法iter(f, sentinel),第一个参数f必须是可调用对象,该对象 return将结果,而不是yield它。

来自Python documentation

  

如果给出了第二个参数 sentinel ,则 object 必须是可调用的对象。在这种情况下创建的迭代器将调用 object ,并且每次对其__next__()方法的调用都没有参数;

所以,这就是您要寻找的答案:

cnt=0

def myfunc():
    global cnt
    cnt += 1
    return "abczdef"[cnt]
#   ^^^^^^

list(iter(myfunc, 'z'))

正如预期的那样,将得到['b', 'c']作为结果(注意缺少'a':在将cnt用作字符串索引之前已对其进行了递增,因此您永远都无法访问"abczdef"[0]):

Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> cnt=0
>>> def myfunc():
...     global cnt
...     cnt += 1
...     return "abczdef"[cnt]
...
>>> list(iter(myfunc, 'z'))
['b', 'c']
>>>