Checking range of function argument in python - python

What to do with functions which are numerically valid, but physically out of range?
The reason, I would like my programm to tell me and stop, if the physically correct range is left.
I thought about using the ValueError exception for this error handling.
Example:
def return_approximation(T):
#return T only if it is inbetween 0 < T < 100
return T

Python has the assert-statement for this kind of argument restrictions.
def return_approximation(T):
assert 0 < T < 100, "Argument 'T' out of range"
return T

You should raise an exception called ValueError.
if 0 < T < 100:
raise ValueError('T must be in the exclusive range (0,100)')

I'm not sure about what you mean by physically.
Generally speaking, if the out-of-range error is caused by external data, you're supposed to raise an exception; if the error comes from your own data, you may use assert to abort the current execution.

You can simply, restrict the returned value to T if it matches your conditions else return None, like so:
>>> def f(T):
return T if 0 < T < 100 else None
>>> f(100)
>>> f(99)
99
>>> f(0)
>>> f(1)
1
EDIT: solution with exceptions:
>>> def f(T):
if 0 < T < 100:
return T
else:
raise ValueError
>>> f(100)
Traceback (most recent call last):
File "<pyshell#475>", line 1, in <module>
f(100)
File "<pyshell#474>", line 5, in f
raise ValueError
ValueError
>>> f(99)
99
>>> f(0)
Traceback (most recent call last):
File "<pyshell#477>", line 1, in <module>
f(0)
File "<pyshell#474>", line 5, in f
raise ValueError
ValueError
>>> f(1)
1
You can even output your own message for more clarity:
>>> def f(T):
if 0 < T < 100:
return T
else:
raise Exception('T is out of Range')
>>> f(100)
Traceback (most recent call last):
File "<pyshell#484>", line 1, in <module>
f(100)
File "<pyshell#483>", line 5, in f
raise Exception('T is out of Range')
Exception: T is out of Range

Related

Hello, need to solve a problem like such:

If the number in the line is already wroten, I must print 0 and if it's not, I must print 1.
Got ValueError and tried to catch it, but it fails.
a=int(input())
b=input()
n='1 '
c=b.split()
for i in range(a-1):
l=c[0]
c.remove(l)
d=c.index(l)
try:
a=a
except ValueError as ve:
if d > 0:
c = c.replace(l,'zero')
else:
c=c.replace(l,'one')
for amogus in range(a):
a=a.replace('one',1)
a=a.replace('zero',0)
print(a)
The error tracebacks like so:
Traceback (most recent call last):
File "program.pys3", line 8, in <module>
d=c.index(l)
ValueError: '1' is not in list
The first part of your loop is like this:
for i in range(a-1):
l = c[0]
c.remove(l)
d = c.index(l)
l is set to the first item in the list c. You then remove that item. The last line above then tries to find the index of that item again. This will work if there is another one, but if not will throw the error you report.
Did you mean to put the last line inside the try:?
for i in range(a-1):
l = c[0]
c.remove(l)
try:
d = c.index(l)
except ValueError as ve:
if d > 0:
c = c.replace(l,'zero')
else:
c = c.replace(l,'one')
Now a friendly warning: if this fixes the reported error you will encounter another one.

How can I throw TypeError with message inside if statement in Python?

What I want to do
I would like to fix my current code to pass the coding challenge, Codewars Prefill an Array.
I hope to learn how to throw TypeError with message with if statement in this case.
Create the function prefill that returns an array of n elements thatall have the same value v. See if you can do this without using a loop.
You have to validate input: v can be anything (primitive orotherwise) if v is ommited, fill the array with undefined if n is 0, return an empty array if n is anything other than an integer or integer-formatted string (e.g. '123') that is >=0, throw a TypeError
When throwing a TypeError, the message should be n is invalid, where
you replace n for the actual value passed to the function.
Code Examples
prefill(3,1) --> [1,1,1]
prefill(2,"abc") --> ['abc','abc']
prefill("1", 1) --> [1]
prefill(3, prefill(2,'2d'))
--> [['2d','2d'],['2d','2d'],['2d','2d']]
prefill("xyz", 1)
--> throws TypeError with message "xyz is invalid"
Problem
I have passed 4 sample tests among 5 sample tests, but I cannot pass the below one.
prefill("xyz", 1)
--> throws TypeError with message "xyz is invalid"
Error Message
Traceback (most recent call last): File "main.py", line 8,
in <module> prefill('xyz', 1) File "/home/codewarrior/solution.py",
line 3, in prefill if int(n): ValueError: invalid literal for int() with base 10: 'xyz'
Current code
def prefill(n,v):
if int(n):
result = [0] * int(n)
for i in range(len(result)):
result[i] = v
return result
else:
return TypeError, str(n) + "is invalid"
Developing Environment
Python 3.4.3
You can use a try-except to catch the error, and throw for example another one:
def prefill(n,v):
try:
n = int(n)
except ValueError:
raise TypeError("{0} is invalid".format(n))
else:
return [v] * n
For example:
>>> prefill(3,1)
[1, 1, 1]
>>> prefill(2,"abc")
['abc', 'abc']
>>> prefill("1", 1)
[1]
>>> prefill(3, prefill(2,'2d'))
[['2d', '2d'], ['2d', '2d'], ['2d', '2d']]
>>> prefill("xyz", 1)
Traceback (most recent call last):
File "<stdin>", line 1, in prefill
ValueError: invalid literal for int() with base 10: 'xyz'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in prefill
TypeError: xyz is invalid
You do not per se need to specify an exception to raise. In case you want to re-raise the exception, simply writing raise is sufficient. You can furthermore specify a tuple of exceptions to catch, and make v optional here, for example:
def prefill(n,v=None):
try:
n = int(n)
except (TypeError, ValueError):
raise TypeError("{0} is invalid".format(n))
else:
return [v] * n
Use the raise keyword to raise an exception, rather than return it. raise is used to generate a new exception:
>>> raise TypeError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError
In this example I raised the TypeError by using the exception class directly. You can also create instances of the error like this:
>>> t=TypeError()
>>> raise t
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError
Doing it that way allows various properties to be set on the object before using raise. The problem posted includes this requirement:
When throwing a TypeError, the message should be n is invalid, where you replace n for the actual value passed to the function.
That is an example of a situation where it is necessary to create an instance of the error and set a message property on it before using raise. That can still be done in one line:
>>> raise TypeError("foo")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo
To catch exceptions, use a try-except block, rather than an if block:
x = 'hello, world!'
try:
y = x / 2
except TypeError as e:
e.args = (*e.args, str(x) + " is not valid")
raise
This will raise an error:
TypeError: ("unsupported operand type(s) for /: 'str' and 'int'", 'hello, world! is not valid')
note that you can check the datatype of a variable using type():
>>> x = 5
>>> type(x)
<class 'int'>
>>> if type(x) == int:
... print("it's an int")
...
it's an int
Also, the code sample could be simplified to:
return [v for _ in range(n)]

difference in behavior within if statements for python

i had two statements and my friend is claiming to me they are not the same. i believe they are. I was wondering if they are and if they aren't is there an example where the behavior is different.
if (n != p and c/n > 5.15):
if (c/n > 5.15 and n !=p):
They could be different due to the short-circuiting behavior of and. If the first operand of and is false, the second is not evaluated. So if c/n > 5.15 raises an exception (for instance if n is zero), the first if may work (that is, not raise any error) while the second causes an error. Here is an example:
c = 0
n = 0
p = 0
# No error, no output because the condition was not true
>>> if (n != p and c/n > 5.15):
... print "Okay!"
# Raises an error
>>> if (c/n > 5.15 and n !=p):
... print "Okay!"
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
if (c/n > 5.15 and n !=p):
ZeroDivisionError: division by zero

In python, when argument data type are NaN, how to return an NaN, not an TypeError

e.g. I defined an function which needs several input arguments, if some keyword arguments not being assigned, typically there be an TypeError message, but I want to change it, to output an NaN as the result, could it be done?
def myfunc( S0, K ,r....):
if S0 = NaN or .....:
How to do it?
Much appreciated.
Edited:
def myfunc(a):
return a / 2.5 + 5
print myfunc('whatever')
>python -u "bisectnewton.py"
Traceback (most recent call last):
File "bisectnewton.py", line 6, in <module>
print myfunc('whatever')
File "bisectnewton.py", line 4, in myfunc
return a / 2.5 + 5
TypeError: unsupported operand type(s) for /: 'str' and 'float'
>Exit code: 1
What I want is, the myfunc(a) only accpets an number as the input, if some other data type like a string = 'whatever' inputed, I don't want to just output an default error message, I want it to output something like return 'NaN' to tell others that the input should be an number.
Now I changed it to this, but still not working,
btw, is none the same as NaN? I think they're different.
def myfunc(S0):
if math.isnan(S0):
return 'NaN'
return a / 2.5 + 5
print myfunc('whatever')
>python -u "bisectnewton.py"
Traceback (most recent call last):
File "bisectnewton.py", line 8, in <module>
print myfunc('whatever')
File "bisectnewton.py", line 4, in myfunc
if math.isnan(S0):
TypeError: a float is required
>Exit code: 1
Thanks!
You can capture the TypeError and do whatever you want with it:
def myfunc(a):
try:
return a / 2.5 + 5
except TypeError:
return float('nan')
print myfunc('whatever')
The Python Tutorial has an excellent chapter on this subject.
def myfunc(S0 = None, K = None, r = None, ....):
if S0 is None or K is None or r is None:
return NaN
Yes, to generate a NaN you do float('nan'):
>>> import math
>> float('nan')
nan
>>> math.isnan(float('nan'))
True
So you can return float('nan') wherever you want to return the nan. I recommend you just raise the exception, though.
If you don't want to use TypeError, then how about using AttributeError?
def myfunc(a):
try:
return a / 2.5 + 5
except AttributeError:
return float('nan')
print myfunc('whatever')

Why doesn't all() stop on the first False element?

From the docs, all is equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
Then why do I get this output:
# expecting: False
$ python -c "print( all( (isinstance('foo', int), int('foo')) ) )"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'
When:
# expecting: False
$ python -c "print( isinstance('foo', int) )"
False
One (fairly ugly) way to get the behaviour you want is via lambdas:
all(f() for f in (lambda: isinstance('foo', int), lambda: int('foo')))
Arguments are evaluated before calling a function. In this case first you have to create the tuple you pass to all.
all never had a chance to check them, the exception was thrown before that.
>>> int('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'
Your intuition regarding all is correct; you only need to work a little harder to set up a lazy sequence. For example:
def lazy():
yield isinstance("foo", int) # False
yield int("foo") # raises an error, but we won't get here
>>> all(lazy())
False
>>> list(lazy())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in lazy
ValueError: invalid literal for int() with base 10: 'foo'
If the desire to stop evaluation after the first False condition is specifically to perform type checking, something like this will work better:
if not isinstance(other, MyClass):
return False
else:
return all((self.attr1 == other.attr2,
self.attr2 == other.attr2)) # etc.
Simplified version from #catchmeifyoutry:
return isinstance(other, MyClass) and all((self.attr1 == other.attr2,
self.attr2 == other.attr2)) # etc.

Categories