I'm curious what is the 'proper' pythonic way of handling this error with a while loop. I could simply check the string to see if it has a [-1] character beforehand in this example, but the actual code this example of my problem is based on is much more complicated.
try:
while mystring[-1] == '!' #Will throw an error if mystring is a blank string
print("Exclamation!")
mystring = mystring[:-1]
return mystring
except:
return ""
Effectively my problem is that my while loop is contingent on a check that, occasionally after some processing within the loop, will throw an error. The above is just a (perhaps overly) simplified illustration of that problem. I fixed it with a series of try: excepts:'s, but I feel like that's not the "correct" way to be addressing this issue.
Two things your current code does that you shouldn't do:
Catches any exception, you should catch just the specific exception of interest
Includes the whole loop in the try block, you should if at all possible only include that statement/expression that raises the exception
If you find yourself using while loops a lot in python, it suggests that you aren't making the most effective use of python. Given python's toolset you should almost always be using some sort of for loop. Without seeing a real sample of your code, I can't say whether that's actually true. If you want help in that area, post some code at http://codereview.stackexchange.com
A general solution to this problem is to write a function which handles the exception and use that.
def last_character(string):
try:
return string[-1]
except IndexError:
return ' '
while last_character(mystring) == '!'
mystring = mystring[:-1]
return mystring
In fact, in many cases already have exception-less equivalents to the standard constructs. This loop can easily be written using the .endswith() method. By using those or crafting your own you can deal with the exceptions most cleanly.
For your example, you could simply do something like:
while mystring and mystring[-1] == '!':
print("Exclamation!")
mystring = mystring[:-1]
return mystring
This will work because it will short-circuit and end the loop if mystring is empty, so you will never try to access the -1 index of an empty string
Edit: As Winston pointed out, you can get rid of all of the special casing by using str.endswith as in the following code
while mystring.endswith('!'):
print("Exclamation!")
mystring = mystring[:-1]
return mystring
Use mystring.rstrip('!') to remove the'!' characters at the end of the string ;-)
If the problem is much more complicated, the proper way is to catch the IndexError thrown by the operation.
try:
while mystring[-1] == '!' #Will through an error if mystring is a blank string
print("Exclamation!")
mystring = mystring[:-1]
return mystring
except IndexError:
return ""
Another way is to check the string for emptyness and avoiding using the operation which raises the exception:
while mystring and mystring[-1] == '!': # lazy boolean expression evaluation
mystring = mystring[:-1]
return mystring
Other version without the lazy boolean expression evaluation:
if not mystring:
return mystring
while mystring[-1] == '!':
mystring = mystring[:-1]
if not mystring:
break
return mystring
I personnaly favor the second version, especially if you change mystring[-1] == '!' with mystring.endswith('!') (but in that case you don't need to check for emptyness, because endswith already does this for you).
Related
I am trying to solve the following problem in python (not for anything, just trying to learn how to code), and I keep getting the time limit exceeded error.
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Can someone please explain why the code won't run?
Detail on my logic: I am trying to check if the input has any values (or else return true immediately), then whether it has any closed parentheses next to each other. The idea is that every true input must have either '()', '[]', or '{}' somewhere in the string. Then, I would remove those pairs until either there are no more characters, and I know it's true, or it can't find any and it is false.
If this is a poor way to think about the problem and you plan to offer a different way, please also help me understand why this code doesn't run.
class Solution:
def isValid(self, s: str) -> bool:
l = ['()','[]','{}']
while s != '':
while l[0] in s or l[1] in s or l[2] in s:
try:
s.replace(s[s.index(l[0])],'')
except:
ValueError
try:
s.replace(s[s.index(l[1])],'')
except:
ValueError
try:
s.replace(s[s.index(l[2])],'')
except:
ValueError
continue
return False
return True
s.replace(...) returns the modified string. It doesn't modify s in place; it can't, since strings are immutable.
There are other mistakes but I'll leave them as an exercise for you to figure out. Fixing this will at least get you past the infinite loop.
In addition to the above answers, it seems like you are trying to catch a ValueError when s.index() fails.
The code you have will instead catch any exception, not just ValueError.
You can do it like this:
try:
# try code
except ValueError as e:
# handle ValueError
Many times I find myself writing code in the following form:
conditional_str = ''
if condition:
conditional_str = ' blah blah'
output = 'my constant string' + conditional_str
I find it a bit cumbersome, and looking for a concise way of doing it.
One way is to put this piece of code to a function.
output = conditional_str_concat(const_str, condition, conditional_str )
But I was wondering if there are better pythonic way of doing it.
I think the only other clean solution would be a conditional expression:
# Concatenate an empty string if "not condition"
output = 'my constant string' + (' blah blah' if condition else '')
This is essentially what you had before, just inline. Whether or not it's better is up for debate.
You could make it a function as you mentioned, but I don't think it should be the job of a function to conditionally call code for you based on a passed-in flag (condition). I think the caller should just handle condition themselves.
I have a large string full of byte code so there is no spaces, I am trying to search for a specific part of that code.
For example;
byte_code = 'ergewyegt6t4738t8347tygfhfh47tg4378t58437t485t454gyfofby3gyfg34t5t6435t3465tg3465t4'
The value I am looking for is 'fhfh47tg'.
I have tried the .find String method but did not have much luck.
As mentioned before, the string has no spaces.
I'd expect the output to be true once it has found the pattern within the string.
You can use the in (__contains__) test for substring existence:
if 'fhfh47tg' in byte_code:
print('Match found')
You can also look at methods like str.find, str.index FWIW.
Using re.search is one option:
if re.search(r'fhfh47tg', byte_code):
print("MATCH")
else:
print("NO MATCH")
I think you can do
if 'fhfh47tg' in byte_code:
return True
or
return 'fhfh47tg' in byte_code
you can try the following:
byte_code = 'ergewyegt6t4738t8347tygfhfh47tg4378t58437t485t454gyfofby3gyfg34t5t6435t3465tg3465t4'
if 'fhfh47tg' in byte_code:
print("Value is present.")
(you can change the output as per your liking.)
Peace out.
In my Python 3(.5) script I have a simple for loop, that looks like this:
request = "simple string"
ignore = (
# Tuple that contains regex's to ignore
)
for (i, regex) in enumerate(ignore):
if re.search(regex, request):
print("Found regex {0}.".format(i))
return False
Now, this works as expected and the loop stops on the first match that is found.
I understand that the break statement is what is used to break loops in Python.
Knowing this lead to the question: Must I use the break statement to break a loop or could I get away with using the return statement instead?
Keeping this question in mind, would it be better off for my code to look like this:
request = "simple string"
ignore = (
# Tuple that contains regex's to ignore
)
for (i, regex) in enumerate(ignore):
if re.search(regex, request):
print("Found regex {0}.".format(i))
break
return exits a function immediately.
If you are in a loop, that breaks out of the loop and no break is required first.
So no, you are not required to use break if return suits your needs.
Does anybody have a quickie for converting an unsafe string to an int?
The string typically comes back as: '234\r\n' or something like that.
In this case I want 234. If '-1\r\n', I want -1. I never want the method to fail but I don't want to go so far as try, except, pass just to hide errors either (in case something extreme happens).
In this case you do have a way to avoid try/except, although I wouldn't recommend it (assuming your input string is named s, and you're in a function that must return something):
xs = s.strip()
if xs[0:1] in '+-': xs = xs[1:]
if xs.isdigit(): return int(s)
else: ...
the ... part in the else is where you return whatever it is you want if, say, s was 'iamnotanumber', '23skidoo', empty, all-spaces, or the like.
Unless a lot of your input strings are non-numbers, try/except is better:
try: return int(s)
except ValueError: ...
you see the gain in conciseness, and in avoiding the fiddly string manipulation and test!-)
I see many answers do int(s.strip()), but that's supererogatory: the stripping's not needed!
>>> int(' 23 ')
23
int knows enough to ignore leading and trailing whitespace all by itself!-)
import re
int(re.sub(r'[^\d-]+', '', your_string))
This will strip everything except for numbers and the "-" sign. If you can be sure that there won't be ever any excess characters except for whitespace, use gruszczy's method instead.
int('243\r\n'.strip())
But that won't help you, if something else than a number is passed. Always put try, except and catch ValueError.
Anyway, this also works: int('243\n\r '), so maybe you don't even need strip.
EDIT:
Why don't you just write your own function, that will catch the exception and return a sane default and put into some utils module?
try:
x=int("234\r\n".strip())
except ValueError:
x=0
def str_to_int(a):
str_to_int_output=""
for i in range(len(a)):
for b in range(10):
if a[i]==str(b):
str_to_int_output+=a[i]
return int(str_to_int_output)
fn for "str to float" is a bit more comlicated, but i think i can do it if it is needed.
You could just:
def to_int(unsafe_string):
return int(unsafe_string.strip())
But it will throw a ValueError if the stripped unsafe_string is not a valid number. You can of course catch the ValueError and do what you like with it.
Without knowing what kinds of inputs you are expecting, it's hard to say what is 'enough' to solve this. If you are just worried about trailing newlines, then Xavier Combelle's or gruszczy's answer is enough:
try:
x = int(value)
except ValueError:
x = 0
If you have to find any integer, anywhere in a string, then you might need something like this:
import re
try:
x = int(re.search(r'(0|(-?[1-9][0-9]*))', searchstring).group(0))
except TypeError: # Catch exception if re.search returns None
x = 0
Under Python 3.0 (IDLE) this worked nicely
strObj = "234\r\n"
try:
#a=int(strObj)
except ValueError:
#a=-1
print(a)
>>234
If you're dealing with input you cannot trust, you never should anyway, then it's a good idea to use try, except, pass blocks to control exceptions when users provide incompatible data. It might server you better to think about try, except, pass structures as defensive measures for protecting data compatibility rather than simply hidding errors.
try:
a=int(strObj) #user sets strObj="abc"
except ValueError:
a=-1
if a != -1:
#user submitted compatible data
else:
#inform user of their error
I hope this helps.