Variable scoping of “for i in range(XX)” in Python
Frage
This is a exercise for Python, and I am confused about the variable scoping in Python.
"Return True if the given string contains an appearance of "xyz" where the xyz is not directly preceeded by a period (.). So "xxyz" counts but "x.xyz" does not.
xyz_there('abcxyz') → True
xyz_there('abc.xyz')→ False xyz_there('xyz.abc') → True"
This is my answer:
def xyz_there(str):
for i in range(len(str)-2):
if str[i]=='.':
i+=1
continue
elif str[i:i+3]=='xyz':
return True
return False
And it is wrong. xyz_there('abc.xyz') → False
will always return True
. Because the variable i
will always be 0,1,2.... And the i+=1
doesn't mean anything.
Why???
Lösung
It's not that you can't change the value of i
. You can. The trick here is that you are iterating over the contents of the return value of range
. Each time the loop resets you get the next value from that iterable, it does not increment the value of i
to progress the loop.
Andere Tipps
Are you required to use a for loop? This would be a great place for a regular expression. I've modified the example below so I'm not just giving you the answer... Instead of looking for "xyz", I'm looking for "hello". And I'm also trying to avoid seeing a "?" before that "hello".
import re
def hello_there(str):
if re.match("(.*[^\?])?hello.*", str):
return True
return False
The regex pattern consists of:
.*
- any number of non-newline characters at the beginning of the string;[^\?]
- disallowing^
a(n escaped) question mark\?
before everything that follows;hello
- ensuring thathello
will make an appearance;.*
- and ending in any number of other characters.
re.match will return a MatchObject that resolves to a boolean value of True, so it can be used as the condition in the if statement.
>>> hello_there("foohellobar")
True
>>> hello_there("foo?hellobar")
False
>>> hello_there("foohello?bar")
True
simplest answer is:
def xyz_there(str):
for i in range(len(str)-2):
if str[i:i+3] == "xyz" and str[i-1] != ".":
return True
return False