Interesting talk on Python vs. Ruby and how he would like Python to have just a bit more syntactic flexibility.

Steve Howell showell30 at yahoo.com
Fri Feb 19 00:05:04 EST 2010


On Feb 18, 8:27 pm, "sjdevn... at yahoo.com" <sjdevn... at yahoo.com> wrote:
> On Feb 18, 10:58 pm, Paul Rubin <no.em... at nospam.invalid> wrote:
>
 > Steve Howell <showel... at yahoo.com> writes:
> > >> But frankly, although there's no reason that you _have_ to name the
> > >> content at each step, I find it a lot more readable if you do:
>
> > >> def print_numbers():
> > >>     tuples = [(n*n, n*n*n) for n in (1,2,3,4,5,6)]
> > >>     filtered = [ cube for (square, cube) in tuples if square!=25 and
> > >> cube!=64 ]
> > >>     for f in filtered:
> > >>         print f
>
> > > The names you give to the intermediate results here are
> > > terse--"tuples" and "filtered"--so your code reads nicely.
>
> > But that example makes tuples and filtered into completely expanded
> > lists in memory.  I don't know Ruby so I've been wondering whether the
> > Ruby code would run as an iterator pipeline that uses constant memory.
>
> I don't know how Ruby works, either.  If it's using constant memory,
> switching the Python to generator comprehensions (and getting constant
> memory usage) is simply a matter of turning square brackets into
> parentheses:
>
> def print_numbers():
>     tuples = ((n*n, n*n*n) for n in (1,2,3,4,5,6))
>     filtered = ( cube for (square, cube) in tuples if square!=25 and
>                  cube!=64 )
>     for f in filtered:
>         print f
>
> Replace (1,2,3,4,5,6) with xrange(100000000) and memory usage still
> stays constant.
>
> Though for this particular example, I prefer a strict looping solution
> akin to what Jonathan Gardner had upthread:
>
> for n in (1,2,3,4,5,6):
>     square = n*n
>     cube = n*n*n
>     if square == 25 or cube == 64: continue
>     print cube
>
> > > In a more real world example, the intermediate results would be
> > > something like this:
>
> > >    departments
> > >    departments_in_new_york
> > >    departments_in_new_york_not_on_bonus_cycle
> > >    employees_in_departments_in_new_york_not_on_bonus_cycle
> > >    names_of_employee_in_departments_in_new_york_not_on_bonus_cycle
>
> I don't think the assertion that the names would be ridiculously long
> is accurate, either.
>
> Something like:
>
> departments = blah
> ny_depts = blah(departments)
> non_bonus_depts = blah(ny_depts)
> non_bonus_employees = blah(non_bonus_depts)
> employee_names = blah(non_bonus_employees)
>
> If the code is at all well-structured, it'll be just as obvious from
> the context that each list/generator/whatever is building from the
> previous one as it is in the anonymous block case.

I agree that the names don't have to be as ridiculously long as my
examples, but using intermediate locals forces you to come up with
consistent abbreviations between adjacent lines, which adds to the
maintenance burden.  When the requirements change so that bonuses
apply to NY and PA departments, you would have to change three places
in the code instead of one.

To the extent that each of your transformations were named functions,
you'd need to maintain the names there as well (something more
descriptive than "blah").





More information about the Python-list mailing list