Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
363 views
in Technique[技术] by (71.8m points)

python - What are the uses of iter(callable, sentinel)?

So, I was watching Raymond Hettinger's talk Transforming Code into Beautiful, Idiomatic Python and he brings up this form of iter which I was never aware of. His example is the following:

Instead of:

blocks = []
while True:
    block = f.read(32)
    if block == '':
        break
    blocks.append(block)

Use:

blocks = []
read_block = partial(f.read, 32)
for block in iter(read_block, ''):
    blocks.append(block)

After checking the documentation of iter, I found a similar example:

with open('mydata.txt') as fp:
    for line in iter(fp.readline, ''):
        process_line(line)

This looks pretty useful to me, but I was wondering if of you Pythonistas know of any examples of this construct that doesn't involve I/O-read loops? Perhaps in the Standard Library?

I can think of very contrived examples, like the following:

>>> def f():
...     f.count += 1
...     return f.count
... 
>>> f.count = 0
>>> list(iter(f,20))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> 

But obviously this is not any more useful that the built-in iterables. Also, it seems like code smell to me when you are assigning state to a function. At that point, I'd likely should be working with a class, but if I'm going to write a class, I might as well implement the iterator protocol for whatever I want to accomplish.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's a silly example I came up with:

from functools import partial
from random import randint

pull_trigger = partial(randint, 1, 6)

print('Starting a game of Russian Roulette...')
print('--------------------------------------')

for i in iter(pull_trigger, 6):
    print('I am still alive, selected', i)

print('Oops, game over, I am dead! :(')

Sample output:

$ python3 roulette.py 
Starting a game of Russian Roulette...
--------------------------------------
I am still alive, selected 2
I am still alive, selected 4
I am still alive, selected 2
I am still alive, selected 5
Oops, game over, I am dead! :(

The idea is to have a generator that yields random values, and you want to a process once a particular value has been selected. You could e.g. use this pattern in each run of a simulation that tries to determine the average outcome of a stochastic process.

Of course the process you would be modelling would likely be much more complicated under the hood than a simple dice roll...

Another example I can think of would be repeatedly performing an operation until it succeeds, indicated by an empty error message (let's just assume here that some 3rd party function is designed like that instead of e.g. using exceptions):

from foo_lib import guess_password

for msg in iter(guess_password, ''):
    print('Incorrect attempt, details:', msg)

# protection cracked, continue...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...