Python arrays and sting formatting options

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Tue Sep 30 19:40:22 EDT 2008


On Tue, 30 Sep 2008 14:34:31 +0000, Marc 'BlackJack' Rintsch wrote:

> On Tue, 30 Sep 2008 15:42:58 +0200, Ivan Reborin wrote:
> 
>> On 30 Sep 2008 07:07:52 GMT, Marc 'BlackJack' Rintsch <bj_666 at gmx.net>
>> wrote:
>>>=====
>>>from __future__ import with_statement from functools import partial
>>>from itertools import islice
>>>from pprint import pprint
>>>
>>>
>>>def read_group(lines, count):
>>>    return [map(int, s.split()) for s in islice(lines, count)]
>>>
>>>def main():
>>>    with open('test.txt') as lines:
>>>        lines = (line for line in lines if line.strip()) 
>>>        result = list(iter(partial(read_group, lines, 3), list()))
>>>    pprint(result, width=30)
>>>
>>>if __name__ == '__main__':
>>>    main()
>>>=====
>> 
>> I'm afraid I must admit I find the code above totally uncomprehesible
>> (I can't even see where the array here is mentioned - "result"?) and
>> inpractical for any kind of engineering practice I had in mind.
> 
> Learn Python then to understand that code.  ;-)
> 
> There is no array.  The data type is called "list" in Python, so
> `result` is a nested list.  And in Python it quite unusual to build
> lists by creating them with the final size filled with place holder
> objects and then fill the real values in.  Instead lists are typically
> created by appending values to existing lists, using list comprehension
> or the `list()` function with some iterable object.

I would weaken that claim a tad... I'd say it is "usual" to write 
something like this:

alist = []
for x in some_values:
    alist.append(something_from_x)


but it is not uncommon (at least not in my code) to write something like 
this equivalent code instead:

alist = [None]*len(some_values)
for i, x in enumerate(some_values):
    alist[i] = something_from_x


Most often the first way is most natural, but the second way is sometimes 
more natural. It will also be more familiar to somebody coming from 
Fortran, and it is a micro-optimization for large lists because it 
doesn't need to resize the list as it grows.

I stress the *micro*-optimization, because Python lists are highly 
optimized to resize as rarely as possible and as quickly as possible, so 
you're not saving much time.

And Marc, I think you're being a little unfair to the OP, who is clearly 
unfamiliar with Python. I've been using Python for perhaps ten years, and 
I still find your code above dense and hard to comprehend. It uses a 
number of "advanced Python concepts" that a newbie is going to have 
trouble with:

- the with statement acts by magic; if you don't know what it does, it's 
an opaque black box.

- you re-use the same name for different uses, which can cause confusion.

- generator expressions.

- functional programming using partial.

- you call a function that uses a list comprehension with both map and 
iterator slicing inside it.


No wonder the OP had trouble with it. *I* have trouble with it, and would 
need to sit down at the interactive interpreter and play around with it 
for a while to be sure what it actually does. If it was your intention to 
make Python look as obtuse and mysterious as possible, you almost 
succeeded. The one things you missed was to replace the read_group 
function with a lambda in the partial.



-- 
Steven



More information about the Python-list mailing list