440,939 Members | 1,638 Online
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
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 , jblazi 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 , [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 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" 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 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 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 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 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 wrote: On Sat, Jul 31, 2004 at 08:43:52PM -0400, Roy Smith wrote: Tim Peters 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 aone-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 itas: 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 thepurpose -- 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 wrote: [...]It's a two-liner, not a one-liner (although it could be made into aone-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" 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 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 , Bruce Eckel wrote:I know the term "protocol" has been used to describe a language featurein 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'mgoing to guess that a protocol is like an interface in Java, exceptthat it doesn't have a concrete definition anywhere, but it is impliedthrough convention and use. Thus a protocol is a "latent interface." AmI 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" 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" 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 stringstring.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 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. Inother words, computer langauges rarely (if ever -- although I supposeEiffel 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 , Bruce Eckel 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.