string issue

S

Steven Bethard

rbt said:
John said:
You are modifying the list as you iterate over it. Instead, iterate
over a copy by using:

for ip in ips[:]:
...

Just to help popularise the alternative idiom, which IMO is
significantly less cryptic (sane constructors of mutable objects
almost always make a copy, and list is no exception: it's guaranteed
to do so):

for ip in list(ips):
...

Works back to at least Python 1.5.2.

I don't know that that approach is less cryptic. ips is already a
list... it looks cryptic to make it a list again, doesn't it? IMO, the
two are equally cryptic. The epitome of clarity would be copy(ips)...
now *that* makes sense, of course, ips[:] or list(ips) work equally well
to the programmer who has learned them.


This probably seems cryptic until you realize that almost all builtin
mutable objects work this way:

py> def copy(obj):
.... return type(obj)(obj)
....

py> lst = range(5)
py> copy(lst)
[0, 1, 2, 3, 4]
py> lst is copy(lst)
False

py> dct = dict(a=1, b=2)
py> copy(dct)
{'a': 1, 'b': 2}
py> dct is copy(dct)
False

py> st = set(range(5))
py> copy(st)
set([0, 1, 2, 3, 4])
py> st is copy(st)
False

py> from collections import deque
py> dq = deque(range(5))
py> copy(dq)
deque([0, 1, 2, 3, 4])
py> dq is copy(dq)
False

If you're uncomfortable with this form, I'd suggest spending some time
playing around with it -- Python is pretty consistent about this usage
of a builtin type.

Steve
 
N

Nick Coghlan

rbt said:
One last clarification on this. It's OK to modify the elements of a
list, but not the list itself while iterating over it... is that the
correct way to think about this?

Correct - the iteration code bases the iteration on the *old* list structure, so
you can end up with odd behaviour.

Py> l = range(10)
Py> for i in l: del l
....
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: list assignment index out of range
Py> l
[1, 2, 4, 5, 7, 9]

Dictionaries have the same problem, but they include some guards that try to
detect it:

Py> d = dict.fromkeys(range(10))
Py> for i in d: del d
....
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: dictionary changed size during iteration

This feature can't be added to lists because it is possible to iterate sensibly
over a mutating list:

Py> l = range(10)
Py> for i in reversed(l): del l
....
Py> l
[]

Cheers,
Nick.
 
F

Francis Girard

Yes, I also this that comprehension is the clearer way to handle this. You
might also consider the good old "filter" function :

ips = filter(lambda ip: '255' not in ip, ips)

Francis Girard

Le vendredi 4 Février 2005 20:38, rbt a écrit :
Thanks guys... list comprehension it is!

Bill said:
ips = [ip for ip in ips if '255' not in ip]
ips
 
A

Alex Martelli

Bill Mill said:
You are modifying the list as you iterate over it. Instead, iterate over
a copy by using:

for ip in ips[:]:
...
Once you know it, it's neat, and I use it sometimes. However, it's a
little too "magical" for my tastes; I'd rather be more explicit about
what's going on.

Using ips[:] to make a copy on the fly is very idiomatic, but I've never
liked it, personally. I see no reason to prefer it to the even shorter
and arguably less obscure ips*1, for example. My preference is:

for ip in list(ips):


Alex
 
R

Reinhold Birkenfeld

Alex said:
Bill Mill said:
You are modifying the list as you iterate over it. Instead, iterate over
a copy by using:

for ip in ips[:]:
...
Once you know it, it's neat, and I use it sometimes. However, it's a
little too "magical" for my tastes; I'd rather be more explicit about
what's going on.

Using ips[:] to make a copy on the fly is very idiomatic, but I've never
liked it, personally. I see no reason to prefer it to the even shorter
and arguably less obscure ips*1, for example.

"Less obscure"? Either you know the `lst[:]' idiom, or you don't. If you
do, it's fine, if you don't, you will have to look it up to understand
its meaning, and that's a good thing.

Using `lst*1', on the other hand, does not make clear that a copy is
created. If you don't already know what it does, you may assume that
`lst' is left alone.
My preference is:

for ip in list(ips):

That is the most intriguing variant, of course.

Reinhold
 
A

Alex Martelli

Reinhold Birkenfeld said:
Using ips[:] to make a copy on the fly is very idiomatic, but I've never
liked it, personally. I see no reason to prefer it to the even shorter
and arguably less obscure ips*1, for example.

"Less obscure"? Either you know the `lst[:]' idiom, or you don't. If you
do, it's fine, if you don't, you will have to look it up to understand
its meaning, and that's a good thing.

I disagree.
Using `lst*1', on the other hand, does not make clear that a copy is
created. If you don't already know what it does, you may assume that
`lst' is left alone.

And indeed it is -- whatever object is bound to the name 'lst' is not
modified in the least (neither would it be by slicing lst[:], of
course). But the RESULT of x*1 is a DISTINCT object from x whenever it
matters -- i.e., whenever x is mutable. x[:] *MIGHT* not be a distinct,
separate, independent copy if x is, e.g. a Numeric.array:

x = Numeric.arange(7)
y = x[:]
x[3]=23

now y is modified too. Change the middle statement into 'y = x*1', and
the third statement won't alter y. So, *WHAT ON EARTH* could possibly
make this weird 'x[:]' form preferable to 'x*1'?! It's MUCH more
obvious that the second one returns an independent, separate object
initially equal to x -- because it does so in many more cases than those
in which x[:] does it! I'm not arguing FOR x*1 -- I'm arguing AGAINST
x[:] as being even remotely acceptable.

That is the most intriguing variant, of course.

It's very down to earth because the result is obviously a list, whatever
'ips' might turn out to be -- no mystery there, and thus, no intrigue.
Maybe we should have a simpler way to specify ``an iterator that is
INDEPENDENT from any possible changes in the iterable we're passing'',
for this specific use case -- but we don't, and I don't think that
copy.copy(ips) is a substantial improvement (it would fail when ips is a
file, or a generator-iterator, or many other kinds of iterators, for
example). list(ips) may do more work than necessary (e.g., if ips were
a tuple) but at least its semantics are quite plain and obvious.


Alex
 
R

Reinhold Birkenfeld

Alex said:
So, *WHAT ON EARTH* could possibly
make this weird 'x[:]' form preferable to 'x*1'?! It's MUCH more
obvious that the second one returns an independent, separate object
initially equal to x

..>> x = 2
..>> y = x*1
..>> x is y
True
..>>

just-kidding-ly yours,

Reinhold
 
A

Alex Martelli

Reinhold Birkenfeld said:
Alex said:
So, *WHAT ON EARTH* could possibly
make this weird 'x[:]' form preferable to 'x*1'?! It's MUCH more
obvious that the second one returns an independent, separate object
initially equal to x

.>> x = 2
.>> y = x*1
.>> x is y
True
.>>

just-kidding-ly yours,

You're just snipping a crucial side-observation which I had put in
exactly to avert such irrelevant diversions:
whenever it
matters -- i.e., whenever x is mutable.

Immutable types are allowed to collapse any two equal but "distinct"
objects into one identity -- that's always the case, I acknowledged that
in my sentence which I just quoted and which you had failed to quote
again, and I don't see what's funny in this procedure and the time it's
wasting, for me and for every reader of this group, now and in the
future from archives.

I'm sure that by selectively quoting just some of your words and
artfully omitting others I could ``make" you say, not just slightly
imprecise things, but utter and total idiocies. So? What's the point
of this "kidding"? Next time, why don't you just omit, for example, a
"not", when you quote me, so as to make it appear that I was saying
exactly the reverse of what I was obviously saying?


I guess it must be time for me to go away from this group again, if my
time on it is to me spent repeating over and over all sorts of asides
which people "just kidding" carefully avoid quoting from my posts,
apparently in order to make believe they caught me in anything less than
perfect accuracy. Cheez -- I HAVE been guilty of less than perfect
accuracy in the past (even of outright errors), but not THIS time (if
one has the common decency to look at ALL the words I posted, rather
than a careful selection thereof), so I completely fail to see how you
thought this "kidding" could be fun.

OK, I'm off. Have a nice life.


Alex
 
R

Reinhold Birkenfeld

Alex said:
Reinhold Birkenfeld said:
Alex said:
So, *WHAT ON EARTH* could possibly
make this weird 'x[:]' form preferable to 'x*1'?! It's MUCH more
obvious that the second one returns an independent, separate object
initially equal to x

.>> x = 2
.>> y = x*1
.>> x is y
True
.>>

just-kidding-ly yours,

You're just snipping a crucial side-observation which I had put in
exactly to avert such irrelevant diversions:
whenever it
matters -- i.e., whenever x is mutable.

Immutable types are allowed to collapse any two equal but "distinct"
objects into one identity -- that's always the case, I acknowledged that
in my sentence which I just quoted and which you had failed to quote
again, and I don't see what's funny in this procedure and the time it's
wasting, for me and for every reader of this group, now and in the
future from archives.

Well, I overread your side-observation (can happen if you don't have too
much time and are not accustomed to flying over English text) and,
though I sensed that it was bad, posted my little joke.
I'm sure that by selectively quoting just some of your words and
artfully omitting others I could ``make" you say, not just slightly
imprecise things, but utter and total idiocies. So? What's the point
of this "kidding"? Next time, why don't you just omit, for example, a
"not", when you quote me, so as to make it appear that I was saying
exactly the reverse of what I was obviously saying?

Well, snipping single paragraphs is different from snipping words out of
them.

Sorry. Didn't mean to drive you insane -- your posts are of use, so clpy
(include me) need you in the future.
I guess it must be time for me to go away from this group again, if my
time on it is to me spent repeating over and over all sorts of asides
which people "just kidding" carefully avoid quoting from my posts,
apparently in order to make believe they caught me in anything less than
perfect accuracy. Cheez -- I HAVE been guilty of less than perfect
accuracy in the past (even of outright errors), but not THIS time (if
one has the common decency to look at ALL the words I posted, rather
than a careful selection thereof), so I completely fail to see how you
thought this "kidding" could be fun.

This is the hot Italian temper, I suppose ;) Of course you were right,
and I'm glad to see your posts of today.
OK, I'm off. Have a nice life.

Thanks, I'll do.

Reinhold
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top