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