I would like to have a callable function (because iter() needs it) that gives me a sequential character from a string.
This function has stalled my pc, I had to reset the computer.
cnt=0
def myfunc():
global cnt
cnt+=1
yield "abczdef"[cnt]
list(iter(myfunc,'z'))
You can use the string as an iterable directly:
def characters(string, sentinel):
for c in string:
if c == sentinel:
break
yield c
>>> list(characters('abczdef', 'z'))
['a', 'b', 'c']
A more functional approach, like you had in mind, would be:
from itertools import takewhile
def characters(string, sentinel):
return takewhile(lambda c: c != sentinel, string))
Using the iter(callable, sentinel)
form can be made to work, too, but I find the other solutions more readable:
def characters(string, sentinel):
chars = iter(string)
return iter(lambda: next(chars), sentinel)
list(iter(myfunc,'z'))
is equivalent to:
result = []
while True:
x = myfunc()
if x == 'z':
break
result.append(x)
If you look at what happens when you call myfunc()
:
>>> myfunc()
<generator object myfunc at 0x7f1e0f1020a0>
>>> myfunc()
<generator object myfunc at 0x7f1e0f1020f8>
>>> myfunc()
<generator object myfunc at 0x7f1e0f1020a0>
you see that it creates a new generator object each time it is called.
Obviously none of these objects is equal to 'z'
, so this creates an infinite loop.
With the syntax iter(f, sentinel)
, the first argument f
must be a callable object that return
s the result , not yield
-ing it.
From Python documentation :
If the second argument, sentinel , is given, then object must be a callable object. The iterator created in this case will call object with no arguments for each call to its
__next__()
method;
So, this is the answer you're looking for:
cnt=0
def myfunc():
global cnt
cnt += 1
return "abczdef"[cnt]
# ^^^^^^
list(iter(myfunc, 'z'))
Which, as expected, gives ['b', 'c']
as the result (note on the absence of 'a'
: you incremented cnt
before using it as the string index, so you're never accessing "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']
>>>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.