RFC: For Loop Invariants
DL Neil
PythonList at DancesWithMice.info
Fri Apr 10 19:49:15 EDT 2020
On 11/04/20 8:44 AM, Elliott Dehnbostel wrote:
> If I've done this incorrectly, please let me know so that I can
> improve/revise. I'm new to the Python community and quite enjoy the more
> functional features of Python 3, but have I have a peeve about it. I'd like
> to propose and discuss the following enhancement to Python 3:
>
> *Consider the following trivial for-loop:*
>
> chars = "abcaaabkjzhbjacvb"
> seek = {'a','b','c'}
> count = 0for a in chars:
> if a in seek:
> count += 1
>
> Gross. Twice nested for a simple count.
Agreed!
Interestingly, similar gross-ness appeared recently in a conversation
about input() within while True: (can't recall if 'here' or on Python-Tutor)
However, starting with the (overly) simple case:
>>> chars = "abcaaabkjzhbjacvb"
>>> seek = {'a','b','c'}
>>> len( [ char for char in chars if char in seek ] )
11
NB I don't like this solution and feel that it would need an explanatory
comment, which (also) somewhat proves your 'readability' point...
> ...
> *In summary:*
>
> for a in iterable if cond:
> # code block
>
> *Becomes syntactic sugar for:*
>
> for a in iterable:
> if cond:
> # code block
>
> *Value proposal:*
>
> I assert that the inlined 'if' condition pattern is superior to the
> alternative refactors.
>
> Right now, the way to acquire an invariant without nesting the block would be:
>
> for a in iterable:
> if not cond:
> continue
>
> But this is messy and not particularly Pythonic.
>
> The filter approach uses concepts that should not be necessary for this task.
>
> The comprehension approach has different, undesirable semantics.
Putting aside the trivial-case, above - let's say our string (chars) is
another more complex iterable, eg something sub-classing UserList.
Wouldn't the selection/filter be coded in a method? That way there is
'separation of concerns' between the filter and the iterator.
class MyList( UserList ):
def only_the_good_stuff( self ):
yield #according to filter
...
my_list = MyList( etc )
...
for a in my_list.only_the_good_stuff():
# calmly carry-on
--
Regards =dn
More information about the Python-list
mailing list