Hi John,
On 25/06/19 4:15 AM, johnf wrote:
Hi folks,
I have the following loop (actually repeated many times )
def locChoices(self):
locDS = self.eslocation.getDataSet()
loc_Choices=['<None>']
locKeys=[0]
for row in locDS:
loc_Choices.append(row['facility'])
locKeys.append(row['pkid'])
return loc_Choices,locKeys
where locDS is a tuple of dicts and a row is a dict.
Since I use a lot of similar loops to populate many dropdown controls I
started investigating the use of list comprehensions. But I can't
figure out how to use them in this loop and wonder if it will improve
the performance. The data is not very big - about a thousand rows -
give or take.
So what do you guys think?
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)...
--
Regards =dn
_______________________________________________
Tutor maillist - Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor