[Python-ideas] Modern language design survey for "assign and compare" statements
Terry Reedy
tjreedy at udel.edu
Mon May 21 13:00:51 EDT 2018
On 5/21/2018 9:14 AM, Rhodri James wrote:
> On 21/05/18 12:29, Daniel Moisset wrote:
>> On 21 May 2018 at 12:05, Rhodri James
>> <rhodri at kynesim.co.uk> wrote:
>>> with my usual use cases. What I normally want is the Python
>>> equivalent of:
>>>
>>> while ((v = get_something()) != INCONVENIENT_SENTINEL)
>>> do_something(v);
>> That use case should be covered by
>>
>> for v in iter(get_something, INCOVENIENT_SENTINEL):
>> do_something(v)
>
> There are many ways round my use case, all of them inelegant. That has
> to be one of the less comprehensible alternatives.
The following might be slightly clearer.
item_iterator = iter(get_something, INCONVENIENT_SENTINEL)
for item in item_iterator:
do_something(item)
I think iter is the right thing to use here. I think your contrary
response is a least partly due to unfamiliarity with the two-argument
form of iter and how it abbreviates and encapsulates the alternatives
you already know.
The essential idea of 'iter' is to produce iterators from Python
objects. When the input is a function, sentinel pair, iter returns an
instance of a internal callable_iterator class, equivalent to
class callable_iterator
def __init__(self, function, sentinel)
self.function = function
self.sentinel = sentinel
def __iter__(self):
return self
def __next__(self):
item = self.function()
if item == self.sentinel:
raise StopIteration
return item
If iter were actually written in Python, it might instead return the
generator returned by a generator function encapsulating one of
well-know while loop idioms.
# Double call form.
def function_sentinel(function, sentinel)
item = function()
while item != sentinel
yield item
item = function()
# Loop and a half form; the loop body is essentially the same
# as the body of callable_iterator.__next__, above
def function_sentinel(function, sentinel):
while True:
item = function() # No 'self.'
if item == sentinel: # No 'self.'
break # Instead of 'raise StopIteration
yield item # Instead of 'return item'
The essential idea of for-loops is to cleanly separate sequential
production of items to be processed, in the header, from processing of
each item, in the body. It always calls iter(iterable) for you. If you
need to pass two arguments to iter, you must do it explicitly. The
while alternatives for this case intermix getting and processing items
in the body.
--
Terry Jan Reedy
More information about the Python-ideas
mailing list