By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,939 Members | 1,638 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,939 IT Pros & Developers. It's quick & easy.

transforming a list into a string

P: n/a
Let us assume I have a list like

['1','2','7','8','12','13]

and would like to transoform it into the string

'{1,2},{7,8},{12,13}'

Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)

TIA,

jb

Jul 18 '05 #1
Share this Question
Share on Google+
34 Replies


P: n/a
jblazi wrote:
Let us assume I have a list like

['1','2','7','8','12','13]

and would like to transoform it into the string

'{1,2},{7,8},{12,13}'

Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)

from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)])

'{1,2},{7,8},{12,13}'
Peter

Jul 18 '05 #2

P: n/a
In article <pa****************************@hotmail.com>,
jblazi <jb****@hotmail.com> wrote:
Let us assume I have a list like

['1','2','7','8','12','13]
I'm assuming there's supposed to be another single-quote after the 13?
and would like to transoform it into the string

'{1,2},{7,8},{12,13}'
This works, and is pretty straight-forward:

source = ['1','2','7','8','12','13']
temp = []

while source:
x = source.pop(0)
y = source.pop(0)
temp.append ('{%s,%s}' % (x, y))

result = ','.join (temp)
print result

This prints what you want:

$ /tmp/list2string.py
{1,2},{7,8},{12,13}

Accumulating the repeating bits of the result string in a list, and then
putting them together with a join operation is a common idiom in python.
You can build up strings by doing string addition:

temp = temp + '{%s,%s}' % (x, y)

This will have the same result, but suffers from quadratic run times as
it keeps building and destroying immutable strings.
Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)


How long is "much longer", and how important is it that this runs fast?
The code above runs in O(n). You can probably play some tricks to tweak
the speed a little, but in the big picture, you're not going to do any
better than O(n).

The above code also assumes you have an even number of items in source,
and will bomb if you don't. You probably want to fix that :-)
Jul 18 '05 #3

P: n/a
> In article <pa****************************@hotmail.com>,
[snip]

This works, and is pretty straight-forward:

source = ['1','2','7','8','12','13']
temp = []

while source:
x = source.pop(0)
y = source.pop(0)
temp.append ('{%s,%s}' % (x, y))

result = ','.join (temp)
print result

[snip]

How long is "much longer", and how important is it that this runs fast?
The code above runs in O(n). You can probably play some tricks to tweak
the speed a little, but in the big picture, you're not going to do any
better than O(n).


Are you sure? Did you consider the complexity of list.pop(0)?

Jp
Jul 18 '05 #4

P: n/a
I wrote:
The code above runs in O(n).

Jp Calderone <ex*****@divmod.com> wrote: Are you sure? Did you consider the complexity of list.pop(0)?


I'm assuming list.pop() is O(1), i.e. constant time. Is it not?

Of course, one of my pet peeves about Python is that the complexity of
the various container operations are not documented. This leaves users
needing to guess what they are, based on assumptions of how the
containers are probably implemented.
Jul 18 '05 #5

P: n/a

"Roy Smith" <ro*@panix.com> wrote in message
news:ro***********************@reader1.panix.com.. .
Are you sure? Did you consider the complexity of list.pop(0)?
I'm assuming list.pop() is O(1), i.e. constant time. Is it not?


Yes, list.pop() (from the end) is O(1) (which is why -1 is the default arg
;-).
However, list.pop(0) (from the front) was O(n) thru 2.3.
The listobject.c code has been rewritten for 2.4 and making the latter O(1)
also *may* have been one of the results. (This was discussed as desireable
but I don't know the result.)
Of course, one of my pet peeves about Python is that the complexity of
the various container operations are not documented.


So volunteer a doc patch, or contribute $ to hire someone ;-).

Terry J. Reedy

Jul 18 '05 #6

P: n/a
[Terry Reedy]
However, list.pop(0) (from the front) was O(n) thru 2.3.
The listobject.c code has been rewritten for 2.4 and making the latter O(1)
also *may* have been one of the results. (This was discussed as desireable
but I don't know the result.)


Didn't happen -- it would have been too disruptive to the basic list
type. Instead, Raymond Hettinger added a cool new dequeue type for
2.4, with O(1) inserts and deletes at both ends, regardless of access
pattern (all the hacks suggested for the base list type appeared to
suffer under *some* pathological (wrt the hack in question) access
pattern). However, general indexing into a deque is O(N) (albeit with
a small constant factor). deque[0] and deque[-1] are O(1).

[Roy Smith]
Of course, one of my pet peeves about Python is that the complexity of
the various container operations are not documented.


Lists and tuples and array.arrays are contiguous vectors, dicts are
hash tables. Everything follows from that in obvious ways -- butyou
already knew that. The *language* doesn't guarantee any of it,
though; that's just how CPython is implemented. FYI, the deque type
is implemented as a doubly-linked list of blocks, each block a
contiguous vector of (at most) 46 elements.
Jul 18 '05 #7

P: n/a
Tim Peters <ti********@gmail.com> wrote:
Lists and tuples and array.arrays are contiguous vectors, dicts are
hash tables. Everything follows from that in obvious ways -- but you
already knew that.


OK, so it sounds like you want to reverse() the list before the loop,
then pop() items off the back. Two O(n) passes [I'm assuming reverse()
is O(N)] beats O(n^2).
Jul 18 '05 #8

P: n/a
[Roy Smith]
OK, so it sounds like you want to reverse() the list before the loop,
then pop() items off the back. Two O(n) passes [I'm assuming reverse()
is O(N)]
Yes.
beats O(n^2).


Absolutely. Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)]) '{1,2},{7,8},{12,13}'

Jul 18 '05 #9

P: n/a
Tim Peters <ti********@gmail.com> wrote:
Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)])

'{1,2},{7,8},{12,13}'


Personally, I'm not a big fan of clever one-liners. They never seem
like such a good idea 6 months from now when you're trying to figure out
what you meant when you wrote it 6 months ago.
Jul 18 '05 #10

P: n/a
On Sat, Jul 31, 2004 at 08:43:52PM -0400, Roy Smith wrote:
Tim Peters <ti********@gmail.com> wrote:
Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
>> from itertools import izip
>> items = ['1','2','7','8','12','13']
>> it = iter(items)
>> ",".join(["{%s,%s}" % i for i in izip(it, it)])

'{1,2},{7,8},{12,13}'


Personally, I'm not a big fan of clever one-liners. They never seem
like such a good idea 6 months from now when you're trying to figure out
what you meant when you wrote it 6 months ago.


It's a two-liner, not a one-liner (although it could be made into a
one-liner with enough contortions...).

The only other way I could see to expand this solution would be to write it
as:
it = iter(items)
pairs = izip(it, it)
s = ",".join(["{%s,%s}" % i for i in pairs])

I don't know if three-liners meet your threshold for verbosity ;)

Well, you could write it as:

pairs = []
it = iter(items):
while True:
try:
pair = it.next(), it.next()
except StopIteration:
break
pairs.append(pair)
s = ",".join(["{%s,%s}" % i for i in pairs])

But at that point, the scaffolding is large enough that it obscures the
purpose -- I definitely find this harder to read than the two-liner.

I find Peter's original form easy to read -- if you understand how "izip(it,
it)" works (which is a very simple and elegant way to iterate over (it[n],
it[n+1]) pairs), the rest is very clear.

-Andrew.

Jul 18 '05 #11

P: n/a
Andrew Bennetts <an***************@puzzling.org> wrote:
It's a two-liner, not a one-liner (although it could be made into a
one-liner with enough contortions...).

The only other way I could see to expand this solution would be to write it
as:
it = iter(items)
pairs = izip(it, it)
s = ",".join(["{%s,%s}" % i for i in pairs])

I don't know if three-liners meet your threshold for verbosity ;)
It's better, but I'd unroll it one more step and write:

it = iter (items)
pairs = izip (it, it)
strings = ["{%s,%s}" % i for i in pairs]
s = ",".join (strings)

I'm also not particularly happy about the choice of "it" as a variable
name. The "izip (it, it)" construct makes me think of Dr. Evil :-)
I find Peter's original form easy to read -- if you understand how "izip(it,
it)" works (which is a very simple and elegant way to iterate over (it[n],
it[n+1]) pairs), the rest is very clear.


It's not the izip bit that bothers me in the original, it's the deeply
nested construct of

",".join(["{%s,%s}" % i for i in izip(it, it)])

There's too much going on in that one line to get your head around
easily. I suppose people who are really into functional programming
might find it understandable, but I find it rather obtuse.
Jul 18 '05 #12

P: n/a
Thx. Your solution is perfect for me as speed is not an issue here.

jb
Jul 18 '05 #13

P: n/a
+1

--
Michel Claveau

Jul 18 '05 #14

P: n/a
On Sun, 1 Aug 2004 11:00:32 +1000, Andrew Bennetts <an***************@puzzling.org> wrote:
On Sat, Jul 31, 2004 at 08:43:52PM -0400, Roy Smith wrote:
Tim Peters <ti********@gmail.com> wrote:
> Note that Peter Otten previously posted a lovely O(N)
> solution in this thread, although it may be too clever for some
> tastes:
>
> >>> from itertools import izip
> >>> items = ['1','2','7','8','12','13']
> >>> it = iter(items)
> >>> ",".join(["{%s,%s}" % i for i in izip(it, it)])
> '{1,2},{7,8},{12,13}'
Personally, I'm not a big fan of clever one-liners. They never seem
like such a good idea 6 months from now when you're trying to figure out
what you meant when you wrote it 6 months ago.


It's a two-liner, not a one-liner (although it could be made into a
one-liner with enough contortions...).

Assuming items definition doesn't count in the line count,
items = ['1','2','7','8','12','13']
then one line seems to do it, not that obscurely (depending on your glasses ;-)
",".join(["{%s,%s}"%(n(),n()) for n in [iter(items).next] for i in xrange(0,len(items),2)])

'{1,2},{7,8},{12,13}'
The only other way I could see to expand this solution would be to write it
as:
it = iter(items)
pairs = izip(it, it)
s = ",".join(["{%s,%s}" % i for i in pairs])

I don't know if three-liners meet your threshold for verbosity ;)

Well, you could write it as:

pairs = []
it = iter(items):
while True:
try:
pair = it.next(), it.next()
except StopIteration:
break
pairs.append(pair)
s = ",".join(["{%s,%s}" % i for i in pairs])

But at that point, the scaffolding is large enough that it obscures the
purpose -- I definitely find this harder to read than the two-liner.

I find Peter's original form easy to read -- if you understand how "izip(it,
it)" works (which is a very simple and elegant way to iterate over (it[n],
it[n+1]) pairs), the rest is very clear.

Agreed.

Regards,
Bengt Richter
Jul 18 '05 #15

P: n/a
Roy Smith wrote:
I'm also not particularly happy about the choice of "it" as a variable
name. The "izip (it, it)" construct makes me think of Dr. Evil :-)
Using "it" is just my convention (contradictio in adiecto :-) for iterators
used in a pure algorithm rather than with a meaning determined by a
concrete use case. It's similar to the traditional i in counting loops,
having grown an additional "t" to disambiguate it. If you have a better
name for the purpose, don't hesitate to tell me...
It's not the izip bit that bothers me in the original, it's the deeply
nested construct of

",".join(["{%s,%s}" % i for i in izip(it, it)])

There's too much going on in that one line to get your head around
easily. I suppose people who are really into functional programming
might find it understandable, but I find it rather obtuse.


I don't think three levels can be called "deep nesting". In particular the
"somestr".join() construct is so ubiquitous that your brain will "optimize"
it away after reading a small amount of Python code. But I see my oneliner
meets serious opposition. Well, sometimes a few self-explanatory names and
a helper function can do wonders:

import itertools

def pairs(seq):
it = iter(seq)
return itertools.izip(it, it)

coords = ['1','2','7','8','12','13']
points = []
for xy in pairs(coords):
points.append("{%s, %s}" % xy)

print ", ".join(points)

That should be clear even to someone who has never heard of generators. Note
that pairs() is only called once and therefore does not affect the speed of
execution. Personally, I'd still go with the list comprehension instead of
the above for-loop.

By the way - expanding on Michele Simionato's chop(),
http://mail.python.org/pipermail/pyt...ay/222673.html
I've written a generalized version of pairs():

_missing = object()

def ntuples(seq, N=2, filler=_missing):
""" Yield a sequence in portions of N-tuples.
list(ntuples("abcdefg", 3)) [('a', 'b', 'c'), ('d', 'e', 'f')]
list(ntuples("abc", filler="x"))

[('a', 'b'), ('c', 'x')]
"""
if filler is _missing:
it = iter(seq)
else:
it = itertools.chain(iter(seq), itertools.repeat(filler, N-1))
iters = (it,) * N
return itertools.izip(*iters)

Enjoy :-)

Peter

Jul 18 '05 #16

P: n/a
On Sun, 1 Aug 2004 11:00:32 +1000, Andrew Bennetts <an***************@puzzling.org> wrote:
[...]

It's a two-liner, not a one-liner (although it could be made into a
one-liner with enough contortions...).

Another contortion ;-)
items = ['1','2','7','8','12','13'] assumed defined as before, then one line:
''.join([i%2 and c+'},' or '{'+c+',' for i,c in enumerate(items)])[:-1]

'{1,2},{7,8},{12,13}'

Regards,
Bengt Richter
Jul 18 '05 #17

P: n/a
Peter Otten wrote:

Peter's solution:
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)]) '{1,2},{7,8},{12,13}'


My first thought was:
items = ['1','2','7','8','12','13']
",".join(["{%s,%s}" % i for i in zip(items[::2], items[1::2])])

*'{1,2},{7,8},{12,13}'

Two lines less, but it creates three unnecessary lists.**I*like
Peter's better.

--Steven Rumbalski
Jul 18 '05 #18

P: n/a
On Sat, 31 Jul 2004, Tim Peters wrote:
Absolutely. Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)]) '{1,2},{7,8},{12,13}'
A bit too clever for mine, mostly because neither izip() nor zip() is
guaranteed to process its arguments in a left-to-right order (although
there's no reason for them not to). I'd rather do this:
from itertools import izip, islice
items = ['1','2','7','8','12','13']
it1 = islice(items,0,None,2)
it2 = islice(items,1,None,2)
",".join(["{%s,%s}" % i for i in izip(it1, it2)])

'{1,2},{7,8},{12,13}'

Although it doesn't improve efficiency any (or have that 'slick' feel), it
does prevent needless head-scratching :)

Curious, why isn't slicing of generators defined, using islice(), so "it1
= iter(items)[0::2]" is valid?

Jul 18 '05 #19

P: n/a
[Christopher T King]
...
Curious, why isn't slicing of generators defined, using islice(), so "it1
= iter(items)[0::2]" is valid?


The real question then is why iterators don't, because a
generator-function returns a generator-iterator, and the latter
supplies only the methods in the general iterator protocol (next() and
__iter__()). That protocol was deliberately minimal, to make it easy
for all kinds of objects to play along. islice() was invented long
after. Now that islice() exists, it may indeed make sense to use it
to give a meaning to slice notation applied to iterators. But doing
so requires that iterators implement the appropriate type slots to
"look like" they're also "sequences" (that's how dispatching for slice
notation works), and that's a lot more to ask of objects. If only
some iterators implement it (like generator-iterators), then the
general interchangeability of iterable objects we enjoy today would be
damaged too.
Jul 18 '05 #20

P: n/a

"Tim Peters" <ti********@gmail.com> wrote in message
news:1f************************@mail.gmail.com...
Absolutely. Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)]) '{1,2},{7,8},{12,13}'


While this usage of izip(it,it) is clever (and zip(it,it) behaves the
same), it *breaks* the documented behavior of zip and hence of izip, and
depends on seemingly inessential implementation details of zip/izip (which
is only documented for izip).

The Lib Manual 2.1 zip entry calls the args 'sequences' whereas it should
say 'iterables'. It goes on "This function returns a list of tuples, where
the i-th tuple contains the i-th element from each of the argument
sequences. ... The returned list is truncated in length to the length of
the shortest argument sequence." In fact, even back in 2.2:
it = iter([1,2,3,4])
zip(it,it)

[(1, 2), (3, 4)]

I believe the definition of zip would allow iterator inputs to be handled
by list()ing them (for instance, left to right). A reason to do this might
be to fix the otherwise unknown lengths so that the min could be determined
so that the output list could be preallocated. If this were done, however,
zip(it,it) would output [] instead.

If zip were to build output tuples from the end, which the definition would
also seem to allow, then zip(it,it) above would be [(2,1), (4,3)] instead.
Zip's behavior seems to me undefined for this corner case.

So the doc needs to be updated to specify the args as iterables, not
restricted to sequences, and qualify the 'usual' behavior as depending on
having distinct iterator inputs.

The 5.14.1 Itertool functions izip entry says simply "Like zip() except
that it returns an iterator instead of a list." It also give 'equivalent'
Python code which happens to pin down the behavior for this corner case. I
wonder if this code should really be taken as determinative documentation
rather than as illustrative of possible implementation. (I may ask RH if
need be.) If the former, then the zip doc could reference the izip
equivalent code as specifying its behavior.

Terry J. Reedy

Jul 18 '05 #21

P: n/a
On Sun, 1 Aug 2004, Tim Peters wrote:
[Christopher T King]
...
Curious, why isn't slicing of generators defined, using islice(), so "it1
= iter(items)[0::2]" is valid?


If only some iterators implement it (like generator-iterators), then the
general interchangeability of iterable objects we enjoy today would be
damaged too.


Ah, I see your point. But most functions that expect iterators use iter()
on them first (to iterize sequences), do they not? So long as iter()
supplies the necessary __getslice__ implementation, the world would be
happy. This situation would mirror the situation with list(): though a
user-defined sequence might not implement __getslice__ (and still be
usable as a list), the object returned by list() is guaranteed to.

Jul 18 '05 #22

P: n/a
[Christopher T King]
Ah, I see your point. But most functions that expect iterators use iter()
on them first (to iterize sequences), do they not? So long as iter()
supplies the necessary __getslice__ implementation, the world would be
happy. This situation would mirror the situation with list(): though a
user-defined sequence might not implement __getslice__ (and still be
usable as a list), the object returned by list() is guaranteed to.


The difference is that list() creates a concrete list object from its
argument, but there's no such thing as "a concrete iter object".
Iteration is a protocol, not a type. iter(obj) invokes
obj.__iter__(), and I don't know of any existing __iter__
implementation that returns an object that supports slicing. The only
thing required of __iter__ is that it return an object that supports
the iteration protocol (meaning an object that supports next() and
__iter__() methods). So again, adding the ability to slice too would
mean requiring more of __iter__ methods -- or changing the
implementation of iter() to ignore __iter__ methods and make something
up itself. It's A Visible Change no matter how you cut it.
Jul 18 '05 #23

P: n/a
On Sun, 1 Aug 2004, Tim Peters wrote:
The difference is that list() creates a concrete list object from its
argument, but there's no such thing as "a concrete iter object".
You've got me there.
Iteration is a protocol, not a type. iter(obj) invokes
obj.__iter__(),
Only if obj.__iter__() is defined; otherwise it makes something up using
__getitem__ as appropriate.
and I don't know of any existing __iter__ implementation that returns an
object that supports slicing.
True. Built-in classes (such as list & tupleiterator) would have to be
extended with this function (trivial if they all subclass from a common
base class). As to user classes, I'm proposing this on the assumption
that a programmer would implement their own __getitem__ (I've been saying
__getslice__ previously, __getitem__ is what I should be saying) if the
functionality is so desired, which can be as trivial as setting
__getitem__=islice, provided islice is extended to accept slice objects.
Though, this would break __getitem__ in the case of getting a single
item (I can see where this is heading)...
The only thing required of __iter__ is that it return an object that
supports the iteration protocol (meaning an object that supports next()
and __iter__() methods). So again, adding the ability to slice too
would mean requiring more of __iter__ methods -- or changing the
implementation of iter() to ignore __iter__ methods and make something
up itself. It's A Visible Change no matter how you cut it.


You've made your point. I guess this will just have to go on the "it
would be neat if it worked this way, but it just doesn't" list for now ;)

Jul 18 '05 #24

P: n/a
Sunday, August 1, 2004, 6:51:15 PM, Tim Peters wrote:
Iteration is a protocol, not a type.


I know the term "protocol" has been used to describe a language
feature in a number of languages, but since we have no official
"protocol" support in Python I'm interested in what "we" mean by this
term. I'm going to guess that a protocol is like an interface in Java,
except that it doesn't have a concrete definition anywhere, but it is
implied through convention and use. Thus a protocol is a "latent
interface." Am I close? I'd like to understand this term better.

Bruce Eckel
Jul 18 '05 #25

P: n/a
"Protocol" in python has no meaning beyond normal English. Specifically
the iteration protocol says the iterable must have a __iter__ method
which returns an object that has an __iter__ which returns self, and a
next() method that returns the next thing in the thing being iterated.
When there are no more things, next() raises StopIteration. All of this
is a simple protocol defined by the python language. It doesn't
introduce anything new to the language besides the protocol itself;
__iter__ and next are regular methods and StopIteration is raised just
as any other class can be raised as an exception.

On Sun, Aug 01, 2004 at 07:25:23PM -0600, Bruce Eckel wrote:
Sunday, August 1, 2004, 6:51:15 PM, Tim Peters wrote:
Iteration is a protocol, not a type.


I know the term "protocol" has been used to describe a language
feature in a number of languages, but since we have no official
"protocol" support in Python I'm interested in what "we" mean by this
term. I'm going to guess that a protocol is like an interface in Java,
except that it doesn't have a concrete definition anywhere, but it is
implied through convention and use. Thus a protocol is a "latent
interface." Am I close? I'd like to understand this term better.

Bruce Eckel

Jul 18 '05 #26

P: n/a
On Saturday 31 July 2004 6:44 am, Peter Otten wrote:
jblazi wrote:
Let us assume I have a list like

['1','2','7','8','12','13]

and would like to transoform it into the string

'{1,2},{7,8},{12,13}'

Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)
from itertools import izip
items = ['1','2','7','8','12','13']
it = iter(items)
",".join(["{%s,%s}" % i for i in izip(it, it)])


'{1,2},{7,8},{12,13}'
Peter


This way also works I am not sure how it compares on large sets for memory
usage, cpu time etc.

items = ['1','2','7','8','12','13']
if len(items)%2 == 0:
#the len check is to make sure that the length of the set is evenly
#divisible by 2
output = "{%s,%s}" * (len(items)/2)% tuple(items)
Jul 18 '05 #27

P: n/a
Christopher T King <sq******@WPI.EDU> wrote in
news:Pi**************************************@ccc4 .wpi.edu:
On Sat, 31 Jul 2004, Tim Peters wrote:
Absolutely. Note that Peter Otten previously posted a lovely O(N)
solution in this thread, although it may be too clever for some
tastes:
>>> from itertools import izip
>>> items = ['1','2','7','8','12','13']
>>> it = iter(items)
>>> ",".join(["{%s,%s}" % i for i in izip(it, it)])

'{1,2},{7,8},{12,13}'
>>>
A bit too clever for mine, mostly because neither izip() nor zip() is
guaranteed to process its arguments in a left-to-right order (although
there's no reason for them not to).


You should read an earlier thread on this topic:

http://groups.google.co.uk/groups?th...s.t-online.com

I make exactly that point, that the order isn't guaranteed, and was
refuted fairly convincingly by Peter Otten. The documentation says that
izip is equivalent to a particular reference implementation. Any
implementation which didn't preserve the left to right ordering wouldn't
match the reference:

Peter Otten wrote:
Passing the same iterator multiple times to izip is a pretty neat
idea, but I would still be happier if the documentation explicitly
stated that it consumes its arguments left to right.


From the itertools documentation:

"""
izip(*iterables)

Make an iterator that aggregates elements from each of the iterables.
Like zip() except that it returns an iterator instead of a list. Used
for lock-step iteration over several iterables at a time. Equivalent
to:

def izip(*iterables):
iterables = map(iter, iterables)
while iterables:
result = [i.next() for i in iterables]
yield tuple(result)
"""

I'd say the "Equivalent to [reference implementation]" statement
should meet your request.


Jul 18 '05 #28

P: n/a
[cc'ing Alex so he can jump in if he wants]

In article <ma**************************************@python.o rg>,
Bruce Eckel <Br********@MailBlocks.com> wrote:

I know the term "protocol" has been used to describe a language feature
in a number of languages, but since we have no official "protocol"
support in Python I'm interested in what "we" mean by this term. I'm
going to guess that a protocol is like an interface in Java, except
that it doesn't have a concrete definition anywhere, but it is implied
through convention and use. Thus a protocol is a "latent interface." Am
I close? I'd like to understand this term better.


Alex Martelli gave an excellent presentation on Design Patterns at OSCON,
where he made the point that "interface" is roughly equivalent to syntax,
whereas "protocol" is roughly equivalent to syntax plus semantics. In
other words, computer langauges rarely (if ever -- although I suppose
Eiffel comes close) enforce protocols in any meaningful way.

I'm hoping Alex posts his slides soon.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"To me vi is Zen. To use vi is to practice zen. Every command is a
koan. Profound to the user, unintelligible to the uninitiated. You
discover truth everytime you use it." --*****@lion.austin.ibm.com
Jul 18 '05 #29

P: n/a

"jblazi" <jb****@hotmail.com> wrote in message
news:pa****************************@hotmail.com...
Let us assume I have a list like

['1','2','7','8','12','13]

and would like to transoform it into the string

'{1,2},{7,8},{12,13}'

Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)

TIA,

jb

Heres a one-liner,
items = ['1','2','7','8','12','13']
[(items[x],items[x+1]) for x in range(0,len(items)-1,2)]

[('1', '2'), ('7', '8'), ('12', '13')]

Tom
Jul 18 '05 #30

P: n/a

"jblazi" <jb****@hotmail.com> wrote in message
news:pa****************************@hotmail.com...
Let us assume I have a list like

['1','2','7','8','12','13]

and would like to transoform it into the string

'{1,2},{7,8},{12,13}'

Which is the simplest way of achiebing this? (The list is in fact much
longer and I may have to cut the resulting strings into chunks of 100 or
so.)

TIA,

jb

Try,'
items = ['1','2','7','8','12','13']
import string
string.join([('{'+str(items[x])+','+str(items[x+1])+'}') for x in

range(0,len(items)-1,2)])

Tom
Jul 18 '05 #31

P: n/a
Tim Peters <ti********@gmail.com> writes:
The only thing required of __iter__ is that it return an object that
supports the iteration protocol (meaning an object that supports
next() and __iter__() methods). So again, adding the ability to
slice too would mean requiring more of __iter__ methods -- or
changing the implementation of iter() to ignore __iter__ methods and
make something up itself. It's A Visible Change no matter how you
cut it.


What if object[a:b:c] did the following?

1) if __getslice__ is supplied by object, use it.
2) if __getitem__ is supplied, use it.
3) if __iter__ is supplied, use islice(__iter__(object),slice(a,b,c)).

(IIUC, 1) and 2) are what is done currently. As Christopher pointed
out, for 3) to work, islice would have to modified to accept a slice.)

Would this be backward compatible (a "Visible Change"), or would it
break something?

It seems to parallel other dispatching mechanisms, e.g. (IIUC) "in" is
implemented just using the iterator protocol, unless the object
supplies __contains__.

I like the idea of not needing to know about islice, and just using
the [a:b:c] notation. One of python's strongest features is its
consistency of notation.

Dan
Jul 18 '05 #32

P: n/a


Monday, August 2, 2004, 8:44:38 AM, Aahz wrote:
Alex Martelli gave an excellent presentation on Design Patterns at OSCON,
where he made the point that "interface" is roughly equivalent to syntax,
whereas "protocol" is roughly equivalent to syntax plus semantics. In
other words, computer langauges rarely (if ever -- although I suppose
Eiffel comes close) enforce protocols in any meaningful way.


But what would the syntax be in Python? -- there is none. Perhaps you
mean that in Java a protocol would be an interface plus agreed-upon
semantics, whereas in Python the protocol would be the agreed-upon
(e.g. "latent") interface plus the agreed-upon semantics. In a sense,
both the syntax and semantics would be latent; they would only be
exposed and tested during use, since there is no formalized way to
define them.

In Python, of course, you could simply use a class with "pass" methods
everywhere to define a protocol. If there were some way to write
assertions about the protocol you could include those in the class.

Bruce Eckel
Jul 18 '05 #33

P: n/a
Bruce Eckel wrote:
Monday, August 2, 2004, 8:44:38 AM, Aahz wrote:
Alex Martelli gave an excellent presentation on Design Patterns at OSCON,
where he made the point that "interface" is roughly equivalent to syntax,
whereas "protocol" is roughly equivalent to syntax plus semantics. In
other words, computer langauges rarely (if ever -- although I suppose
Eiffel comes close) enforce protocols in any meaningful way.


But what would the syntax be in Python? -- there is none. Perhaps you
mean that in Java a protocol would be an interface plus agreed-upon
semantics, whereas in Python the protocol would be the agreed-upon
(e.g. "latent") interface plus the agreed-upon semantics. In a sense,
both the syntax and semantics would be latent; they would only be
exposed and tested during use, since there is no formalized way to
define them.

In Python, of course, you could simply use a class with "pass" methods
everywhere to define a protocol. If there were some way to write
assertions about the protocol you could include those in the class.


My reading of Alex' description seems to be the opposite. By definining
protocol to include the semantics, you are basically ensuring that an
implementation with "pass" would not be valid, except for a useless
protocol that defined null semantics. But yes, what you say about the
"latency" is true, and that's how Python works in many areas. You
need decent automated tests to catch certain errors in Python, though
tools like PyChecker can help with some of the ones that compilers
will find in statically typed languages.

-Peter
Jul 18 '05 #34

P: n/a

On 2004 Aug 02, at 16:44, Aahz wrote:
[cc'ing Alex so he can jump in if he wants]

In article <ma**************************************@python.o rg>,
Bruce Eckel <Br********@MailBlocks.com> wrote:

I know the term "protocol" has been used to describe a language
feature
in a number of languages, but since we have no official "protocol"
support in Python I'm interested in what "we" mean by this term. I'm
going to guess that a protocol is like an interface in Java, except
that it doesn't have a concrete definition anywhere, but it is implied
through convention and use. Thus a protocol is a "latent interface."
Am
I close? I'd like to understand this term better.


Alex Martelli gave an excellent presentation on Design Patterns at
OSCON,
where he made the point that "interface" is roughly equivalent to
syntax,
whereas "protocol" is roughly equivalent to syntax plus semantics. In
other words, computer langauges rarely (if ever -- although I suppose
Eiffel comes close) enforce protocols in any meaningful way.

I'm hoping Alex posts his slides soon.


Sorry, ADSL down, leaving for the Alps tomorrow, emergency netting from
an internet cafe` at $$/hour. Hope to have my slides up when I get
back (Aug 17 or thereabouts). But yes, what I deduced as the meaning
of "protocol" from its occasional usage in the literature (about
components, mostly) is that it adds to the interface (syntax==method
names/signatures) the semantics and pragmatics ("you cannot call any
other method after calling close" being more pragmatics than semantics,
at least in linguistics terms). Languages do enforce protocols (e.g.,
raise an exception if you do mistakenly call something else after
calling close), just not "at compile time" (not even Eiffel, where
contract checking is runtime -- not even Haskell for its typeclasses,
which is what I believe comes closest to compiletime protocol
checking).
Alex

Jul 18 '05 #35

This discussion thread is closed

Replies have been disabled for this discussion.