Python Modulo TypeError - python

I wanted to create simple code to test if number is odd or even.
I am using Python 2.7.3.
def oddoreven(a):
try: int(a)
except: return "Error"
if a%2==0: return 1
else: return 0
Instead the code fails with error: TypeError: not all arguments converted during string formatting. The error points to the line beginning with if a%2==0....
While researching this problem I found examples indicating that code like this should work. For example answers to this question offer similar code as solution: python - checking odd/even numbers and changing outputs on number size
So what is wrong with my code?

It's because you first test if a can be converted to an int (which is fine), but then you ignore this test and keep going with the string you provided in argument.
Python is a dynamically typed language, but also strongly typed, which means you can change the type of a variable after it's been declared, but this change has to be explicit (more about this here).
In your case, it means you can't do if a % 2 == 0 if a is a string.
You could do this for instance:
def oddoreven(a):
try:
my_int = int(a)
except TypeError:
return "The argument provided could not be converted into an int"
if my_int % 2 == 0:
return 1
else:
return 0

the int function doesn't change the a in-place, you need to assign it to a :
>>> def oddoreven(a):
... try: a=int(a)
... except: return "Error"
... if a%2==0: return 1
... else: return 0
...
>>> oddoreven('2')
1
>>> oddoreven('5')
0
>>> oddoreven('a')
'Error'

As user2357112 stated. (int)a does not convert a to a int. so when you check its modulus you still must convert it.
def oddoreven(a):
try: int(a)
except: return "Error"
if int(a)%2==0: return 1
else: return 0
print oddoreven(32)
works fine.
As a side note, catching any exception is generally frowned upon. You may want to narrow it down like:
def oddoreven(a):
try: int(a)
except TypeError: return "Error"
if int(a)%2==0: return 1
else: return 0
print oddoreven(32)

Related

How to convert float to integer strictly, without rounding?

I wish to find a way to achieve the following: With the likes of 5.0, return 5. With the likes of 5.1, which cannot equal any integer, return Error.
Currently I use int() together with an "if integer != float". However this has problems, for instance I won't be able to tell whether the inequality was caused by the likes of 5.1 or the likes of 1111111111111111.0(and even larger numbers).
Also this is extremely troublesome compared with a potential, simple, one-line command. So is there a command in Python that does this?
Float objects in Python have an is_integer() predicate.
def strict_int(x):
if x.is_integer():
return int(x)
raise ValueError
Note that int objects do not have this method. You'll get an attribute error if you try to call this on an int.
If you wanted some error value instead of an exception, you can use a one-liner like this
int(x) if x.is_integer() else 'Error'
Simply use math as suggested in this answer by #Anthony V like this:
>>> frac, whole = math.modf(5.0)
>>> if frac ==0.0:
... print("this is a whole")
... else:
... print("this is not whole and should return the Error")
This should work easily.
I'm not sure whether there's a more idiomatic way to do this, but intuitively, you can just compare the value of the int and the float and return only when they are equal.
That is
def weird_cast(my_float):
if int(my_float) == my_float:
return int(my_float)
return None # or some error
def return_int(a):
if int(a)==a:
print(int(a)) #you can store the integer value in separate variable #also b = int(a)
#instead of using print you can use return b or int(a)
else:
print('Error') #or you can use return 'Error'
a = 5.0
return_int(a)
Maybe another easier way is to minus with the round down number with itself.
if the remainder is more than 0.0 and less than 1.0, then we can call it a float otherwise integer
def IntegerSanityCheck ( num ):
remainder = abs ( round ( num ) - num )
if ( remainder > 0.0 ) and ( remainder < 1.0 ):
print "Float"
else:
print "Integer"
or you can use math as suggested by user2906838

Function handling floating point numbers to produce a boolean

I've been struggling with the following Boolean problem:
Write a function even_int that consumes any type of data, produces True if it is an even integer, and produces False otherwise.
I wrote:
def even_int(any):
return type(any) != type("a") and float(any % 2 == 0.0)
Feedback on your program:
Make sure your function works when the input is a floating point number.
Don't really understand this feedback. I put the float in front so that should be covered. I also tried without the float or the decimal on the 0.
I think you should just directly check if any is an integer type. I also don't think you need to put a float around any % 2 == 0
def even_int(value):
return isinstance(value, int) and value % 2 == 0
EDIT:
if you want to accept floats as well,
def even_int(value):
return isinstance(value, (float, int)) and value % 2 == 0
I would try this - it's pythonic in that it asks for forgiveness rather than permission by trying to convert to an int (this means it works for strings as well) and catches the TypeError to return False if that doesn't work either.
def even_int(v):
try:
return int(v) % 2 == 0 #will trigger exception if v cannot be cast to int
except (TypeError, ValueError):
return False
EDIT: Simplified based on comments

Python conventions with respect to if conditions

In python, is it frowned upon to use extra conditions within an if statement to avoid error, or should this be done separately from the if statement?
Example:
I want to make sure that d, which will be either a empty string or a number string is not blank and not less than 1. If d is a empty string, it can not be converted to a float. The statement is evaluated as false before trying to convert to float so I don't get an error. Is this bad practice?
def main():
d = "2.25"
check_d(d)
d = "0"
check_d(d)
d = ""
check_d(d)
this looks prettier to me
def check_d(d):
if d and float(d) >= 1:
return True
print('d must be defined with value 1 or greater')
return False
this was my first instinct
def check_d_old(d):
try:
if float(d) >= 1:
return True
except:
pass
print('d must be defined with value 1 or greater')
return False
You don't need the if d part if you include it in the try. Something like this would work, where either you'll get a ValueError if it's not a number, or it'll raise a ValueError if it is a number but under 1.
def check_d(d):
try:
if float(d) >= 1:
return 0
else:
raise ValueError()
except ValueError:
print('d must be defined with value 1 or greater')
return 1
It's fine using extra conditions, but if you can skip a few unnecessary ones, it'll run faster overall. Also, try to not just use except, find out which type of error you want to be looking for.
The first is fine assuming that d will always fit your criteria but the second example is more robust.
For example when d = "a" the condition if d and float(d) >= 1: will raise the ValueError where as the try: except will catch it and work properly.
So if your criteria of "d will be either a blank string or a number string" is absolute then the first is fine, however if d could have other values then you may want to use the second.

True and False Statements, finding variable types

Im trying to decide whether a string variable is a valid integer or float, ive tried try statements but using ASCII seems to be better. I can't get this to work, probably something with the returns and boolean.
def validation(valid):
var=input("no...")
state=True
y=0
for x in range(len(var)):
if state==False or y==2:
valid=False
return valid
if var[x] == chr(46) or chr(48) <= var[x] <= chr(57):
if var[x] == chr(46):
y+=1
state=True
else:
state=False
valid=True
valid = validation(valid)
print(valid)
The ASCII characters 46 and 48-57 are a decimal point and numbers 0-9. If there more than one decimal point (representing by y) than it also returns a false statement.
Simple and powerful approach:
def isNum(txt):
try:
float(txt)
return True
except ValueError:
return False
There is a much simpler way to do this:
try:
float(x)
except ValueError as e:
print e
print "Not a float"
else:
try:
int(x)
except ValueError as e:
print e
print "not an integer"
You can combine these into a method pretty easily.
Your code isn't very efficient, and it doesn't handle negative numbers, or floats written in scientific notation. Using try, as in fiacre's answer is the standard way to do this in Python.
But to answer your question, you don't have a return statement after the for loop, so if all your tests succeed your function returns the default value of None. So you just need to put a return True at the end of your function.
You can make your code a little more efficient by iterating over the string values and testing the characters directly rather than indexing into the string and using chr(). Eg,
for c in var:
if c == '.' or '0' <= c <= '9':
# etc
Alternatively,
valid_chars = set('-.0123456789')
for c in var:
if c in valid_chars:
# etc
FWIW, in your existing code Python has to re-calculate chr(46) etc on every loop. Sure, that's a pretty fast operation, but it's still wasteful.
Also, there's no need to have both state and valid in the function.

Tuple with missing value

I have a function in python that does error checking on a string. If the function finds an error it will return a tuple with an error code and an identifier for that error. Later in the program I have the function that handles the error. It accepts the tuple into two variables.
errCode, i = check_string(s,pathType)
check_string is the function that produces the tuple. What I want it to does is return just zero if there is no error. When a zero is returned the above code seems to fail because there is nothing for the variable i.
Is there an easy way to get this to work or do I just need to have the program return a tuple of 0 and 0 if no error is found?
I would use the exception system for this.
class StringError(Exception):
NO_E = 0
HAS_Z = 1
def string_checker(string):
if 'e' not in string:
raise StringError('e not found in string', StringError.NO_E)
if 'z' in string:
raise StringError('z not allowed in string', StringError.HAS_Z)
return string.upper()
s = 'testing'
try:
ret = string_checker(s)
print 'String was okay:', ret
except StringError as e:
print 'String not okay with an error code of', e.args[1]
You could use None as the value for error
def check_string(s,pathType):
# No error
return (None, i)
Why not simply check the length of the tuple before trying to retrieve the values?
err_tup = check_String(s, pathType)
if len(err_tup) == 2:
errCode, i = err_tup
else: # assuming it can only be 1 otherwise
errCode = err_tup
This would work without making any changes to the rest of your code that generates the tuple, and is semantically clear.
Based on "Simple is better than complex."
If you are going to return zero:
foo = func()
if not foo:
print 'No errors'
else:
# foo is tuple

Categories