1

Suppose I have the following list:

a = ["hello",
     "hi",
     "bye"]

I move the elements around, and, by mistake, I end up with:

a = ["hello",
     "bye"
     "hi"]

which is a list of 2 elements: "hello" and "byehi".

  1. How can I have Python detect this mistake?

    Currently I ended up with:

    assert(len(a)==3)
    

    which of course requires update whenever I add an element to the list.

  2. How to decrease the possibility of this mistake (of course other than being careful)?

    Is there some other separator for lists that won't merge strings that way, for example?

    Is there a linter or an external tool that can detect that?

robertspierre
  • 3,218
  • 2
  • 31
  • 46
  • Heads up that this isn't exclusive to lists. You would have the same "problem" in a tuple, set or dict literal. Generally, this can happen *everywhere* you want to place a syntactical element between strings but forget. – MisterMiyagi Mar 01 '22 at 14:24
  • Would you accept using a linter or external tool as an answer, or do you only want solutions based on existing Python syntax? – kcsquared Mar 01 '22 at 14:32
  • @kcsquared yes absolutely. I'm modifying the question – robertspierre Mar 01 '22 at 14:58

3 Answers3

4

You can't, really, short of good unit tests. However, you are allowed to have a trailing comma, which means you can uniformly follow every element with a ,, rather than only separating elements with a ,.

This is really only a typographic convention; while it helps avoid such errors, it's not a substitute for testing.

a = [
    "hello",
    "hi",
    "bye",
]

(Using separate lines for all list elements and the brackets will also make diffs simpler to read, making your code reviewers happy.)

chepner
  • 497,756
  • 71
  • 530
  • 681
1

There's no alternate separator that I'm aware of, but there are a few things that might help.

First, you could try initializing the list in one line, if it fits in a reasonable amount of space, where the absence of the separator might be more noticeable.

a = ["hello", "hi", "bye"]

Second, you could try making the entire thing a literal string and then splitting on a newline:

a = """hello
hi
bye""".split('\n')

Third, you could try putting the closing bracket on its own line, and making sure that every line of the list declaration (including the last element) has a comma at the end. This is syntactically valid, and my preferred approach.

a = [
    "hello", 
    "hi", 
    "bye",
]
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • 2
    The second option just replaces missing commas with trailing whitespace as a source of errors. – chepner Mar 01 '22 at 14:20
-1

I think your issue isn't your list or its delimiter. I think your problem is the operation on the elements in the list that is changing the elements. To avoid this length update, I suggest wrapping your operation in a try catch until you figure out what command is altering the elements.

# assuming a is not very big

b = a.copy()

try:
  for i in a:
  *operation on a.list*

except:
  len(a)!= len(b)

del b

There is a step in your code where a updates such that a = a.operation. You can check what your length will be by making a copy b ahead of the try catch. This way you don't have to hard code the length.

  • no, I'm moving the elements around by hand as described. The real list is much longer BTW. – robertspierre Mar 01 '22 at 14:58
  • "I think your problem is the operation on the elements in the list that is changing the elements." Is there any reason why you think that? How do you expect the ``try`` ``except`` to fix it or even just to have any effect at all? – MisterMiyagi Mar 01 '22 at 15:48
  • The try and except will not allow the manipulation to occur in the event that the manipulation changes the length array. it is simple; he/she is modifying the elements within the list. If you modify the elements in the list, the list length will change. The try except will not allow this to move forward. The copy is simply a a check before and after the operation. – Michael Skaro Mar 02 '22 at 16:29
  • "The try except will not allow this to move forward." How so? There will be no exception thrown in the ``try:`` body, so the ``except:`` body with the check is not even run – not that it would have an effect either. – MisterMiyagi Mar 02 '22 at 16:43