1

I have stepped on small piece of code that made me wandering:

Style1 (assumed textbook example):

  mylist = ['a','b','c']
  for item in mylist:
      do_someting_with(item)

and Style2 (code seen around):

mylist = ['a','b','c']
for item in mylist[:]:
    do_someting_with(item)

Both styles render to the same result (in theory and practice) but there could be some subtle difference in execution. Is there a reason for style2 or that is simply a bad code that could be more clear?

ljgww
  • 3,418
  • 6
  • 19
  • 21
  • Briefly: when `do_something` modifies `mylist`. – TigerhawkT3 Feb 27 '17 at 09:56
  • @TigerhawkT3: I don't know if this is a *real* duplicate since this question asks the rationale behind the style, not how to remove elements. Removing elements from such list is only an example where it is useful. – Willem Van Onsem Feb 27 '17 at 09:58
  • @WillemVanOnsem - The path is different, but the destination is the same. Reading that page answers this question. – TigerhawkT3 Feb 27 '17 at 09:59
  • @WillemVanOnsem - I mean, it's the _exact content of your answer here_. – TigerhawkT3 Feb 27 '17 at 09:59
  • @TigerhawkT3: yeah but you can also argue that adding elements can be dangerous, since it can result in an infinite list, etc. So one can provide an example with *no overlap*. The description says "*This question has been asked before and already has an answer.*"... This does not hold for the provided duplicate. – Willem Van Onsem Feb 27 '17 at 10:00
  • @WillemVanOnsem - It also says "If those answers do not fully address your question...". Does "How do I do X? - With Y." need a "What's the point of Y? - X."? This page adds nothing useful to the site. – TigerhawkT3 Feb 27 '17 at 10:02
  • @TigerhawkT3: well it does not fully address the problem. For instance another scenario that is not adressed is that it can create an infinite loop when adding elements. – Willem Van Onsem Feb 27 '17 at 10:04
  • @WillemVanOnsem - Yes, it does fully address the problem. This is no different from, say, closing "why do we need `isclose()`?" with the canonical floating-point question. – TigerhawkT3 Feb 27 '17 at 10:06
  • @TigerhawkT3: so in your opinion we should burinate the regex tag if there is a page that asks "Write me a full regex manual"? Furthermore in you example there is no subset-superset relation. The two are equivalent. Here there can be several lists of reasons why to use `[:]`... – Willem Van Onsem Feb 27 '17 at 10:08
  • @WillemVanOnsem - I know it feels bad when a question you answered gets dupehammered, but there's really no need to waste my time with straw man arguments. Good day. – TigerhawkT3 Feb 27 '17 at 10:09
  • @TigerhawkT3: not at all. I even sometimes mark a question I answered as a duplicate later, and upvote people that downvoted me. But here it feels as if it is conflict with the first course I ever took in college (and aced with a triple A): mathematical reasoning :). – Willem Van Onsem Feb 27 '17 at 10:12
  • I do not believe it is duplicate. I have asked for reasoning not for adding or removing of items. Did not even think about that aspect. – ljgww Feb 27 '17 at 11:08
  • @TigerhawkT3 'Briefly: when do_something modifies mylist' - not necessarily. I mostly work with lists in immutable fashion (items are non volatile, cause I get them as result of some other process). As mentioned, when I am dealing with lists that are mutable I rather opt to deque (that promise better performance), so I never had in my mind list volatility as a part of a problem or cause of specific style. Given conclusion/condition is your own interpretation. Also I believe that this question is more general than offered duplicate. – ljgww Feb 27 '17 at 13:24

1 Answers1

2

The main reason to do that is because mylist[:] generates a copy of mylist. This can be useful if you want to alter mylist in the loop. For instance if you want to remove elements that are less than 5:

for item in mylist[:]:
    if item < 5:
        mylist.remove(item)

will work whereas the first style will fail.

Another example is that it can result in an infinite loop. For instance:

for item in mylist:
    mylist.append(item+1)

will loop forever, and you probably only wanted to add an e+1 for every e in the original list (something like: mylist += [item+1 for item in mylist]). The following code will not go into an infinite loop:

 for item in mylist[:]:
    mylist.append(item+1)
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • therefore 2 aspects are to consider for using the style2: safety and convenience. Liked this argument. Fact that sub-range makes new immutable list rather that dealing with original (mutable) list is essential. Thank you for shedding this light. – ljgww Feb 27 '17 at 11:11
  • I did not think about mutability of the list because I rarely change lists that I am working on. In such case (mutability) I would prefer to use deque rather than list. – ljgww Feb 27 '17 at 13:19
  • @ljgww: well if you do not change the list, you can use a tuple which guarantees that you cannot alter it. – Willem Van Onsem Feb 27 '17 at 13:20
  • @[Willem Van Onsem] I do not get tuples as result of my processing (3rd party library), I get lists of elements (and these are usually as is). Learning about safety of sub-range helps me a lot to make code safer as even that I get the list from the library using sub-range guarantees that subsequent code would not alter otherwise (presumably) mutable original. – ljgww Feb 27 '17 at 13:28