I am working on an app programmed with Python and Kivy. I was getting a strange bug and ended up tracking it to this line:
if string.startswith(word): ...do stuff
I defined "word" empty by default (word=""), but that resulted in an expected behaviour: it always checks True, even if the string var is not empy! Example:
key = "" words = ["test1", "teste2", "teste3"] [print("yes") for word in words if word.startswith(key)]
This resulted in 3 prints (I expected zero):
yes yes yes
This was not what I expected. After some research I found out that even the count() method has this strange behavior when counting empty strings:
This printed "6". I thought "WTF", how can this be, it should not have empty strings! After some research I found out that this was happening because Python always interprets a string as a concatenation between empty strings, example: "a", in the background is "''+"a"+''". So "a".count("") returns 2 (one empty string at start, other at the end. In the other hand, "aa" in the background is ""+"a"+""+"a"+"", and "aa".count("") returns 3.
That is why the method startswith("") always returns True for every string no matter what it contains.
Honestly, even thought I understand the logic and always knew about the concatenation in strings and am used to it, this is not very intuitive at first, was not expecting some string standard methods to interpret it this way, took me some time to debug.
A simple solution in my app scenario, for skipping the True check on empty strings, was adding "and x" (=if x is not empty) to the code above (but it turns it more verbose, it would be more Pythonic if startswith() had a flag for disabling this behaviour):
key = "" words = ["test1", "teste2", "teste3"] [print("yes") for x in words if x.startswith(key) and x]