[Tutor] replacing a loop

johnf johnf at jfcomputer.com
Mon Jun 24 18:24:51 EDT 2019


Thank you - it worked!  I'm glad you are no longer sleepy!

Actually I wanted the naming to remain consistent with the other loops

So the name of the function/method (it is in a class) caused the use of 
the underscore

locChoices == location choices

def locChoices(self) cause me to use loc_Choices in the code.

I am torn about the readability of the code - at least in my mind I can 
read the loop a lot easier than I can read the comprehension.

Of course I considered the use of a function where I passed the required 
parameters.  But the issue is the access to the data - that getDataSet() 
was a performance hit when I used a passed parameter.  I could have 
opened/accessed/retrieve the data during the opening but thought it best 
to use a lazy data access as needed.

Today was not really about performance but more about learning to use 
the comprehension.  You see I did attempt to do create the 
comprehension.  But after seeing your code I realized that I had the '[' 
and the '{' confused.  I believed I had to use '{'.  I just reviewed a 
tutorial off the net and that was what they were using.

Thanks again,

Johnf


>
> Just because this morning I needed something to kick-start my sleepy 
> brain into being able to "think"...
>
>
> When most people think of 'multiples' in the context of 
> list-comprehensions, they are talking about "nested-loops" - which are 
> easy-enough (or at least, well-documented).
>
> However, I've often wondered about the multiple being on the 
> 'left-hand side' of the equation/expression, and whether that is even 
> possible?
>
> It is!
> Thus:
>
> python3
> Python 3.6.8 (default, Mar 21 2019, 10:08:12)
> [GCC 8.3.1 20190223 (Red Hat 8.3.1-2)] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>
> # build the data-structure (I hope)
> >>> d1 = { 'pkid':1, 'facility':'here' }
> >>> d2 = { 'pkid':2, 'facility':'there' }
> >>> d3 = { 'pkid':3, 'facility':'nowhere' }
> >>> locDS = ( d1, d2, d3 )
>
> # let's check that the data-format is as-described?
> >>> type( locDS )
> <class 'tuple'>
> >>> for row in locDS: print( row )
> ...
> {'pkid': 1, 'facility': 'here'}
> {'pkid': 2, 'facility': 'there'}
> {'pkid': 3, 'facility': 'nowhere'}
> # are we on the right track?
>
> # this is the original code and approach
> >>> loc_Choices = [ '<None>' ]
> >>> locKeys = [ 0 ]
> >>> for row in locDS:
> ...     loc_Choices.append( row[ 'facility' ] )
> ...     locKeys.append( row[ 'pkid' ] )
> ...
> # which (I hope) shows the existing (and desired) results
> >>> print( loc_Choices )
> ['<None>', 'here', 'there', 'nowhere']
> >>> print( locKeys )
> [0, 1, 2, 3]
>
> # we can do the list inits, cf leaving it to the list comprehension
> >>> loc_Choices = [ '<None>' ]
> >>> locKeys = [ 0 ]
>
> # but how might we achieve this using a (single) list comprehension?
> >>> [ [ loc_Choices.append( row[ 'facility' ] ), locKeys.append( row[ 
> 'pkid' ] ) ] for row in locDS ]
> # in (proper) code, I'd format this over two lines (at least)
>
> # correct me if I'm wrong, but these o/ps will
> # 'disappear into the ether' when run within a pgm...
> [[None, None], [None, None], [None, None]]
>
> # leaving us with 'the proof of the pudding'
> >>> print( loc_Choices )
> ['<None>', 'here', 'there', 'nowhere']
> >>> print( locKeys )
> [0, 1, 2, 3]
> >>>
>
>
> Possible considerations:
>
> 1 some sample data would have eased the way/its lack leaves room for 
> misinterpretation
>
> 2 a list comprehension normally executes more quickly than the 
> traditional (long-form) multi-line code-block. However, it would be 
> worth measuring that on your particular machine h/w and Py__version__. 
> The other 'efficiency' is readability, but "elegance" is largely a 
> matter of (personal) taste. So that ('mine-field') I leave to you...
>
> 3 taking the multi-line code-block and splitting it into TWO separate 
> (consecutive) list comprehensions (one for loc_Choices and the other 
> for locKeys) will most-likely be noticeably MORE 'expensive'
>
> 4 it is no matter if row/the locDS tuple dict-elements contain more 
> key-value pairs
>
> 5 during code review, my colleagues would delight in criticising the 
> choice of names such as locKeys - describing them as "JavaScript" (a 
> 'dirty word' to some), loc_Choices as contrary to PEP-8 ("flake", or 
> whatever), etc - despite that I have a little 'set' of abbreviations 
> with which I do the same, eg locNR. YMMV!
>
> 6 however, this simple boy will venture criticism of the inconsistency 
> in using the underline word-separator, eg locKeys but loc_Choices. 
> Even more potential for confusion: locChoices and loc_Choices!?
>
> 7 consider the data structures (outside of our view, here). Assuming 
> there are more elements in each 'loc dict', might it be just as easy 
> to leave the two pertinent elements 'there' and iterate over locDS 
> when actually applied. Alternately, perhaps it might be better to 
> construct a dictionary with the 'pkid's as keys and the 'facility' as 
> values for direct-access application? Not knowing how the structure(s) 
> will be utilised makes this pure speculation!
>
> 8 any?every time "similar loops" are found, re-factor to a function
> (let's see if that philosophy kicks-off a retort or two...)
>
> 9 was it Knuth who described "premature optimisation" as "evil"? 
> Certainly I'm a believer in 'make it work before you make it better'. 
> So, (after all that!) what are we really achieving here? With such 
> quantities, is it critical to 'save time'? If so, is this part of the 
> code really the greatest time-sink?
> (and we're back to the 'readability' consideration, previously mentioned)
>
>
> Thanks, for the provocation into answering this long-held question - 
> and for the fact that my brain isn't sleepy any longer.
> (mind you, such exertion suggests it must be time for a tea-break)...


More information about the Tutor mailing list