pylint woes

Chris Angelico rosuav at gmail.com
Sat May 7 22:50:46 EDT 2016


On Sun, May 8, 2016 at 12:15 PM, DFS <nospam at dfs.com> wrote:
> On 5/7/2016 9:36 PM, Chris Angelico wrote:
>>
>> On Sun, May 8, 2016 at 11:16 AM, DFS <nospam at dfs.com> wrote:
>>>
>>> street = [s.split(',')[0] for s in addr]
>>> city   = [c.split(',')[1].strip() for c in addr]
>>> state  = [s[-8:][:2] for s in addr]
>>> zipcd  = [z[-5:] for z in addr]
>>
>>
>> So you're iterating over addr lots of times, and building separate
>> lists. As an alternative, you could iterate over it *once*, and have a
>> single object representing an address.
>
> I like the idea of one iteration, but how?   (I'll be trying myself before I
> check back in)
>
> Remember, it's required to split the data up, to give flexibility in
> sorting, searching, output, etc.

Start by unpacking the comprehensions into statement form.

street = []
for s in addr:
    street.append(s.split(',')[0])
city = []
for c in addr:
    city.append(c.split(',')[1].strip())
state = []
for s in addr:
    state.append(s[-8:][:2])
zipcd = []
for z in addr:
    zipcd.append(z[-5:])

Now see how you're doing the same thing four times? Let's start by
keeping it the way it is, but combine the loops.

street, city, state, zipcd = [], [], [], []
for a in addr:
    street.append(a.split(',')[0])
    city.append(a.split(',')[1].strip())
    state.append(a[-8:][:2])
    zipcd.append(a[-5:])

Side point: I prefer collections to be named in the plural, so these
would be "streets", and "addrs". This lets you follow a very simple
rule of iteration: "for item in collection" or "for singular in
plural". In this case, "for address in addresses" is classic
iteration.

So, now that you have a single loop picking up the different pieces,
it's easy to build up a simple object that represents an address.

# Either this
from collections import namedtuple
Address = namedtuple("Address", ["street", "city", "state", "zipcd"])
# or this
from types import SimpleNamespace
class Address(SimpleNamespace): pass

addresses = []
for a in addr:
    addresses.append(Address(
        street=a.split(',')[0],
        city=a.split(',')[1].strip(),
        state=a[-8:][:2],
        zipcd=a[-5:],
    )

Voila! One iteration, and a single object representing an address.

> I saw a cool example where someone built a list and used it to do a bulk
> INSERT.  That probably won't work well here, because one of the options I
> give the user is # of addresses to store.  So I do invididual INSERTs using
> the 'for j in range()' method, which makes it easier to track how many
> addresses have been stored.

You could slice it if you actually want that.

>>> Why is it better to zip() them up and use:
>>>
>>> for item1, item2, item3 in zip(list1, list2, list3):
>>>      do something with the items
>>>
>>> than
>>>
>>>
>>> for j in range(len(list1)):
>>>    do something with list1[j], list2[j], list3[j], etc.
>>
>>
>> Because 'j' is insignificant here, as is the length of the list.
>
> Sorry, but I don't understand what you mean by insignificant.  j keeps track
> of the position in the list - regardless of the length of the list.

Right, but *who cares* what the position is? All you want to do is the
"do something" bit. Don't think in terms of concrete and discrete
operations in a computer; think in the abstract (what are you trying
to accomplish?), and then represent that in code.

>> What
>> you're doing is iterating over three parallel lists - not counting
>> numbers. Imagine that, instead of lists, you just have *sequences* -
>> ordered collections of things. You can follow a recipe without knowing
>> the numbers of the individual lines; you just need to know the
>> sequence. Here, iterate over this collection:
>>
>> * Collect ingredients.
>> * Cream the butter and the sugar.
>> * Sift the salt into the flour.
>> * Fold the mixture into an origami crane.
>>
>> These instructions work whether they're numbered or not.
>
> Again, not following you.
>
>
> The only reason
>
> for j in range(len(list1)):
>     do something with list1[j], list2[j], list3[j], etc.
>
> or
>
> for item1, item2, item3 in zip(list1, list2, list3):
>     do something with the items
>
> works is because each list has the same number of items.

Sure, but who cares what each item's position is? All that matters is
that they have corresponding positions, which is what zip() does.

Imagine you don't even have the whole lists yet. Imagine someone's
still writing stuff to them as you work. Maybe they're infinite in
length. You can't iterate up to the length of list1, because it
doesn't HAVE a length. But you can still zip it up with other parallel
collections, and iterate over them all.

ChrisA



More information about the Python-list mailing list