Как я могу получить символ из строки - PullRequest
0 голосов
/ 26 марта 2019

Я хотел бы иметь вызываемую функцию (потому что она нужна iter ()), которая дает мне последовательный символ из строки.

Эта функция остановила мой компьютер, мне пришлось перезагрузить компьютер.

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

list(iter(myfunc,'z'))

Ответы [ 2 ]

2 голосов
/ 26 марта 2019

Вы можете использовать строку как итеративную непосредственно:

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', поэтому это создает бесконечный цикл.

0 голосов
/ 26 марта 2019

С синтаксисом iter(f, sentinel) первый аргумент f должен быть вызываемым объектом, который return s является результатом , а не yield -из него.

С Документация Python :

Если задан второй аргумент 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']
>>>
...