Use assert for control flow

纵然是瞬间 提交于 2020-03-06 04:36:57

问题


I am trying to check if a word has a trailing semicolon. I have the position of the word within a long string, and I want to check if the character at the position start of word + length of word is a :. It can be that the word is the last word in the string, and therefore trying to get the next char will raise an IndexException

I have three ideas:

1) Check that we are not at the end of the string, and then check that it is not semicolon

semicolon_pos = pos_word + len(word) # Possible position
if semicolon_pos < len(long_string) and long_string[semicolon_pos] == ':':
    # do something...
else:
    # do something else

Not what it is normally considered pythonic

2) Try-except the semicolon extraction and the equality for the semicolon

semicolon_pos = pos_word + len(word) # Possible position
try:
   if long_string[semicolon_pos] == ':':
      # Do something
   else:
      # do something else (which is the same as in the except clause)

except IndexError:
    # do something else

Looks a little bit weird, to extract and then nested. And I have to do a little trick to avoid the code duplication

3) Try-except the semicolon extraction and an assertion to make sure it is a semicolon

semicolon_pos = pos_word + len(word) # Possible position
try:
    assert long_string[semicolon_pos] == ':'
    # do something
except (IndexError, AssertionError):
    # do something else

Structure is flatter and it is easily read, but I have the feeling that is abusing exceptions usage.

What do the python folks say? thanks in advance.


回答1:


The simplest way is just to use a slice as a subscript. Slices don't throw IndexError:

semicolon_pos = pos_word + len(word) # Possible position
if long_string[semicolon_pos:semicolon_pos+1] == ':':
   # Do something
else:
   # do something else 



回答2:


Definitely a misuse of assertions. Reason: assertions aren't even executed when the code is run with the -O flag.

The recommended way to use assertions is to check for "impossible" conditions resulting from a mistake in the algorithm (post-conditions). For pre-conditions and program logic, one should use ordinary exceptions.




回答3:


(string[index] if index < len(string) else None) == ':'




回答4:


I think it is easier this way:

#considering mylongstring contains the word
#+1 for the possible colon
mylongstring[:pos_word + len(word) + 1].endswith(':')

Or, if the long string is very long you don't want to copy too much:

mylongstring[pos_word:pos_word + len(word) + 1][-1] == ':'


来源:https://stackoverflow.com/questions/21132710/use-assert-for-control-flow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!