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
Related
I don't see why the following expression evaluates to False:
>>> 1 in [1,2,3] == True
False
in and == has the same precedence and groups left to right, but:
>>> (1 in [1,2,3]) == True
True
and
>>> 1 in ([1,2,3] == True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable
Where is the problem with the parenthesis?
Comparison operators at the same level "chain". You may have seen something such as 10 < x < 25, which expands to (10 < x) and (x < 25).
Similarly, your original expression expands to
(1 in [1,2,3]) and ([1,2,3] == True)
The first expression evaluates as True, as you already know. The second expression returns False, giving the result you see.
I have a statement like this.
I just want to know which of the two assert statement has thrown the exception.
try:
assert re.search("xyz", statement)
assert re.search("abc", statement)
except AssertionError:
print "AssertionError : Expected Error message not found"
Thanks for the answer.
As mentioned in The assert statement docs, you can give an expression after the assertion test expression; that second expression will be passed in the AssertionError. Here's a simple demo:
for n in (-5, 10, 20):
try:
assert 0 <= n, '%d is too low' % n
assert n <= 10, '%d is too high' % n
print('%d is ok' % n)
except AssertionError as err:
print "AssertionError:", err
output
AssertionError: -5 is too low
10 is ok
AssertionError: 20 is too high
That second expression doesn't have to be a string, it can be anything. Since assertions should only be used to verify program logic, not to validate user data, I generally don't bother passing a nicely-formatted string, I just pass a tuple containing the relevant values, and maybe an identifying string. Eg,
assert (a * b > c), ('Bad product', a, b, c)
You could use functions from the traceback module. For example, extract_tb returns a list of tuples (named tuples in Python 3.5 and newer) representing the stack trace entries. Each tuple contains a line number as well as the source text line (if available).
import traceback
try:
assert 1
assert None
except AssertionError as e:
for x in traceback.extract_tb(e.__traceback__, limit=-1):
print(x.lineno, repr(x.line)) # Prints 5 'assert None'
You are able to print the last raised exception with traceback.print_exc(). An example:
>>> import traceback
>>> try:
... a = 1 / 0
... except:
... traceback.print_exc()
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
There is also traceback.format_exc() in case you don't want to print.
Maybe you want to differ the exceptions?Then Getting exception details in Python can help you.
Copying the answer here:
import sys
try:
assert re.search("xyz", statement)
assert re.search("abc", statement)
except AssertionError:
type, value, traceback = sys.exc_info()
Then you can print out the info.
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
When I was looking at answers to this question, I found I didn't understand my own answer.
I don't really understand how this is being parsed. Why does the second example return False?
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
Thanks for any help. I think I must be missing something really obvious.
I think this is subtly different to the linked duplicate:
Why does the expression 0 < 0 == 0 return False in Python?.
Both questions are to do with human comprehension of the expression. There seemed to be two ways (to my mind) of evaluating the expression. Of course neither were correct, but in my example, the last interpretation is impossible.
Looking at 0 < 0 == 0 you could imagine each half being evaluated and making sense as an expression:
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
So the link answers why this evaluates False:
>>> 0 < 0 == 0
False
But with my example 1 in ([1,0] == True) doesn't make sense as an expression, so instead of there being two (admittedly wrong) possible interpretations, only one seems possible:
>>> (1 in [1,0]) == True
Python actually applies comparison operator chaining here. The expression is translated to
(1 in [1, 0]) and ([1, 0] == True)
which is obviously False.
This also happens for expressions like
a < b < c
which translate to
(a < b) and (b < c)
(without evaluating b twice).
See the Python language documentation for further details.
I have written this code:
def reclen(n):
for i in range(1,n):
if (10**i)%n==1:
return(i)
for j in range(1,20):
if reclen(j)==6:
print(j)
And it will run, outputting the integers between 1-20 satisfying 1/n=has 6 recurring digits. If i change the clause in the second loop to:
for j in range(1,20):
if reclen(j)>6:
print(j)
I would expect to get the integers between 1-2 satisfying 1/n=has 6 or more recurring digits, but instead, i get an error, telling me there's a type error. I have tried plastering int() functions in all the outputs, but it seems I'm not allowed to compare the output as anything but exact equal to a value.
In the case where n is 1 in reclen, there will be nothing for your for loop to iterate over so it returns None. e.g.:
>>> def reclen(n):
... for i in range(1,n):
... if (10**i)%n==1:
... return(i)
...
>>> print(reclen(1))
None
None is neither greater than or less than any integer (on python3.x where comparisons of different types are disallowed by default) which is why you get an error.
>>> None > 6
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() > int()