default case for if statement (if not specified) - python

I have a control statement as following:
if x < 0 or x >= ht or y < 0 or y >= wdt:
im_warped[i][j] = 0
else:
im_warped[i][j] = im[x][y]
which gives the same result as following:
if 0 < x < ht and 0 < y < wdt:
im_warped[i][j] = im[x][y]
I am not specifying an else case for the second control statement, eventhough I am sure that such values (exceeding the bounds) do exist. So what exactly is happening here? Do they automatically get assigned to zero / null values (which I think is unlikely)

If you don't have an else block, then nothing else will happen to the data. Your im_warped array will only have an entry modified in accordance with your if statement
The answer to your question, then, depends on what happens to that data before reaching this if statement. If it's a numpy array created with np.zeros, then all of its entries are 0 by default. If it's data that you're getting from somewhere else, those default values could be anything and depend on what the input data looks like.

if statements have blocks, not values. You seem to be confusing this with the ternary operator. For instance, in Tableau, if you write
if condition then
x
else
y
end
then when condition is true, this whole statement will be evaluated as having the value of x. If you write
z = if condition then x else y end
then whenever condition is true, the expression if condition then x else y will be evaluated as being x, and so x will be assigned to z.
In Python, however, if you write
if condition then:
x
Python expects x to not be a value, but an instruction. In your first example, you had im_warped[i][j]=0. This is an instruction: it tells Python to assign 0 to im_warped[i][j]. If you were to write
z = if condition:
x
else:
y
that will return an error in Python, because in Python if-then-else is not the ternary operator, it's a control statement. It does not return any values, conditional or default. Rather, it runs code. The "default", to the extent there is one, is to not run any code. When you wrote if x < 0 or x >= ht or y < 0 or y >= wdt: im_warped[i][j] = 0, it is not the if-then-else statement that is returning a value; you are putting a value of 0 within the code that it is running.
There is a ternary operator in Python, but its syntax is slightly different: it is conditional_result if condition else default. So your first example could be written as
im_warped[i][j] = 0 if x < 0 or x >= ht or y < 0 or y >= wdt else im[x][y]
and if you were to write
im_warped[i][j] = im[x][y] if 0 < x < ht and 0 < y < wdt
without an else, that would return an error.

Related

Multiple conditional statements for list comprehension Python

I have a list with elements that I want to do operations on with 2 conditions.
One condition is to multiply a norm function by -1 if the element is negative or leaving the norm function positive if the element is positive.
The list of values looks like this:
print(values)
-97476.70633454417
-93170.30642401175
-89901.82679086612
-87187.62533194348
-87269.09594982903
-85513.31676486236
-83545.26529198853
-82411.91255123452
-81620.01849452594
As you can see they are all negative (in this experiment).
The code looks like this:
norm_BIC = [(-1.0) * float(i)/max(values) for i in values if i < 0 or float(i)/max(values) for i in values if i > 0]
If I run the code before the or statement it works:
norm_BIC = [(-1.0) * float(i)/max(values) for i in values if i < 0]
Which means it's everything else following that doesn't work because I get an empty list for norm_BIC when running after the or.
How do I fix this condition?
It seems that you are simply filtering out the negative values and turning them positive. The abs function takes the absolute value, turning your inputs positive.
would
norm_BIC = [ abs(float(i))/max(values) for i in values]
not fix your problem?
To achieve "this or that" in a list comprehension you need to use an if expression. This allows you to add an else clause as expected —
values = [
-97476.70633454417,
-93170.30642401175,
-89901.82679086612,
-87187.62533194348,
-87269.09594982903,
-85513.31676486236,
-83545.26529198853,
-82411.91255123452,
-81620.01849452594,
]
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values if i > 0]
The syntax here isn't list-comprehension specific, compare to this if expression —
a = 10 if b < 10 else 20
Running your example values without that final if i.e.
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values]
I get the following output.
[-1.1942744945724522,
-1.1415129295794078,
-1.1014678561595233,
-1.0682137414339221,
-1.0692119109931586,
-1.0477002865491576,
-1.0235879240531134,
-1.0097022038381638,
-1.0]
If you just want to ensure the result of your calculation is positive you could use the built-in abs() function.
norm_BIC = [abs(float(i)/max(values)) for i in values]
You should use an else clause:
norm_BIC = [(-1.0) * float(i)/max(values) if i < 0 else float(i)/max(values) for i in values]

Python: "If" function

This is probably really simple but I can't figure it out.
I have a bunch of lists and I want to call certain lists if they are in the range equal to a value x and any number between x-5 and x +5. i.e. x-5,x-4,x-3,x-2,x-1,x,x+1,x+2,x+3,x+4 and x+5.
At the moment I have
if sum(listname[i])==x:
if sum(listname[i])==x-1:
if sum(listname[i])==x-2:
etc
How can I do it so that it is combined in one "if" function.
I've been thinking on the lines of something like:
if sum(listname[i])==x-5>=x>=x+5:
or
if sum(listname[i])==x or x-1 or x-2 ".. etc":
but neither work.
Can anybody shine some light on this?
A scenario like if sum(listname[i])==x or x-1 or x-2 ".. etc": (which is not valid python) is usually solved with if value in range(start, stop, step):
So you would write:
if sum(listname[i) in range(x-2, x):
# Code for this case here...
Do you simply mean
if x-5 <= sum(listname[i]) <= x+5:
...
...
It looks like you want to check if the sum of the list is between x - 5 and x + 5. To put it in one if statement is simply:
s = sum(listname[i])
if s >= x - 5 and s <= x + 5:
# do stuff
From what I understand from your question. You what to check that whether sum(listname[i]) is between (x-5, x+5)
You can do this in a single if assuming x is a possitive value:
if (sum(listname[i]) >= (x - 5)) and (sum(listname[i]) <= (x+5))

How to create a while loop with tolerance

I'm trying to do some control engineering where I start with a certain value, for example, x = 5 and in the end, it should return x. The goal, in the end, is to find a value for x, where x (beginning) == x (end).
I was thinking about creating a while loop and just adding or subtracting a certain stepsize on x(beginning) till it reaches equilibrium. However, I want some tolerance in my while loop. Like x(beginning) ==x(end)+0.1 would also be fine.
I don't know how to create this in Python and I'm not sure whether this is even the right way to accomplish this
You could do something like this:
# in this example, x is the beginning value, y is the end value
x = 5
y = 10
tolerance = 0.1
while True:
if abs(y-x) <= tolerance:
break
# put your code here
x += 1 # or something else
I think what you are looking for is math.isclose(). With that you can specify both a relative and an absolute tolerance limit.
isclose(a, b, rel_tol=1e-9, abs_tol=0.0)

Assign Variable(True/False) to many conditions

I am doing Grok Learning Course, and have come across a problem. Sorry if I have done anything badly; not a professional at coding:
I am trying to make a variable that will be True/False depending on many conditions:
So,
x = True if y > 2 , g < 4 , n != 3
I have tried different ways to do this like:
Assigning variable to each of my conditions:
if y > 2:
ytrue = True
etc..
However, I want to find a better way of doing it than that, which is long and tedious.
Thankyou.
It's as simple as
x = y > 2 and g < 4 and n != 3
which evaluates to True if all three conditions hold and False otherwise.
As you are new to programming, here's how you read it.
First you evaluate the right hand side which is
y > 2 and g < 4 and n != 3
This is evaluated left to right. First it evaluates y > 2 which will either be True or False. If False the whole right hand side is False and False will be assigned to x. Otherwise it keeps on evaluating all of the other sub-expressions on the right hand side until one of them is False or until you've found every one to be True, in which case the whole right hand side is True.
In either case, True or False, your variable x gets the desired value.
x = y > 2 and g < 4 and n != 3
If you have multiple expressions and if you want to do expression on a expression using and's & or's combinations its better to put it on like this
x= ((y > 2 and g < 4) or n != 3)
Comparison operators like (>, <, !=, etc.) all end up being evaluated down to True or False by the python interpreter.
Python also has Boolean the operators and, or, not (Read more in Section 4.2 of the python docs) but you can use these in combination with the comparison operators to chain them. So your assignment becomes:
x = y > 2 and g < 4 and n != 3
You can use ternary conditional operator :
['false','true'][y > 2 and g < 4 and n != 3]
How it works ?
True == 1, False == 0
because booleans are a subclass of int , so [y > 2 and g < 4 and n != 3] produce a integer value but ['false','true'] takes it as index value.
True gives ['false','true'][1]
And False gives ['false','true'][0]
Test case:
y=4
g=1
n=3
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
false
Test case2:
y=4
g=1
n=1
print(['false','true'][y > 2 and g < 4 and n != 3])
output:
true
Now, if you want you can store the result in a variable :
x=['false','true'][y > 2 and g < 4 and n != 3]
which you wanted i think.

min() arg is an empty sequence

I'm trying to find minimum element in matrix row, but there are two conditions:
1) it must be > 0
2) and this point must be not visited(is_visited[k] is False)
I'm trying to do next:
min(x for x in matr_sum[i] if x > 0 if is_visited[k] is False )
But there is an error: min() arg is an empty sequence
The full block of code:
for k in range(4):
if matr_sum[i][k] == min(x for x in matr_sum[i] if x > 0 if is_visited[k] is False ) and i!=k:
return k
How to resolve it? Or should I write my min() function? Because it works with one condition:
min(x for x in matr_sum[i] if x > 0)
But with two conditions, it doesn't work.
If you want to avoid this ValueError in general, you can set a default argument to min(), that will be returned in case of an empty list. See described here.
min([], default="EMPTY")
# returns EMPTY
Note that this only works in Python 3.4+
There is no problem with the syntax. It's certainly unusual to have two if clauses, but it's allowed. Consider:
print(min(x for x in range(1,300) if x % 3 == 0 if x % 5 == 0))
Output:
15
However:
print(min(x for x in range(1,300) if x % 2 != 0 if x % 2 != 1))
Output:
ValueError: min() arg is an empty sequence
There are no integers that are both odd and even, so there are no values for min to see, so it throws an exception.
I deduce that in your code, there are no values that pass both conditions. Python doesn't allow you to compute "the minimum of no values", mainly because it makes no sense.
You have to decide what you want to do in the case where there is no minimum because there are no values greater than 0. For example, if you don't want to return k in that case then I might re-write your code something like this:
for k in range(4):
if k != i and is_visited[k] is False:
if matr_sum[i][k] > 0 and matr_sum[i][k] == min(x for x in matr_sum[i] if x > 0):
return k
It might not be obvious why this helps, but assuming matr_sum[i] is a list or similar, then once we know matr_sum[i][k] > 0 then we know the generator passed to min isn't empty, so we won't get an exception. Whereas if matr_sum[i][k] <= 0, then it certainly isn't equal to the smallest positive value, so there's no need to compute the min at all. Another way to write that would be:
if matr_sum[i][k] > 0 and not any(0 < x < matr_sum[i][k] for x in matr_sum[i])
Actually, I'd normally write if not is_visited[k], but I leave it as is False since I don't know whether changing it would change the behaviour of your code.
Try this - it creates the list of x values xs and then only tries to find the min if xs is non-empty. You may need to add some logic to handle the case that xs is empty, depending on what your code is doing.
for k in range(4):
if is_visited[k] is False and i != k:
xs = [x for x in matr_sum[i] if x > 0]
if xs and matr_sum[i][k] == min(xs):
return k
Just use and operation for concatenate tow if statement :
min(x for x in matr_sum[i] if x > 0 and if is_visited[k] is False and i!=k)

Categories

Resources