Passing an array as an argument in Python - python

I'm not sure if this is even possible but I'm trying to create a python program that identifies polynomials and identifies all the properties of them. I was trying to make a function similar to the switch() function, and the way that I was going to get around making hundreds of functions for each number of cases for arguments, I wanted to make one of the arguments an array, currently it's throwing me a bunch of errors and I really don't know what I'm supposed to be doing because they don't explain themselves, I've looked around and haven't found anything that works, any help would be greatly appreciated, I'm fairly certain there is a similar function in python but any articles on it are quite confusing, thank you, below is the function I was trying to make.
def switch(checked, check):
for(item in check):
if(item == check):
return True
return False

If you need to simulate a switch statement you can use a helper function like this one:
def switch(v): yield lambda *c: v in c
You can then use it in a C-like style:
x = 3
for case in switch(x):
if case(1,2):
# do something
break
if case(3):
# do something else
break
if case(4,5,7):
# do some other thing
break
else:
# handle other cases
Or you can use if/elif/else statements:
x = 3
for case in switch(x):
if case(1,2): # do something
elif case(3): # do something else
elif case(4,5,7): # do some other thing
else: # handle other cases

To check if something is an item of a list, you don't need to loop through the list. You can just use the in operator:
d = ['abc', 'xyz', 1, 99]
if 'abc' in d:
# True
# do something
if 'mno' in d:
# False
# do something

Did you mean this?
def switch(checked, check):
for item in check:
if item == checked:
return True
return False

Related

Why does it display "local variable referenced before assignment" even I have assigned it in the same function?

def p3(x,y,ls2):
for i in ls2:
if abs(i[0]-x)==abs(i[1]-y):
c=0
break
else:
c=1
if c==0:
return False
else:
return True
Even I have assigned c in the same function, it still displays "local variable 'c' referenced before assignment"
As the comment by Suraj S says, the problem is if ls2 is an empty list (iterable). Even if that were not a problem, c is a local variable inside the for loop and even though Python allows accessing it outside its scope, it is not a good practice to do so. So it is correct to default initialize it first before running the loop. You can default it to 0 or 1 depending on your use case.
Also, practice Boolean Zen. Don't make redundant checks with booleans. It is better to use True and False instead of 0 and 1.
def p3(x,y,ls2):
c = True # default
for i in ls2:
if abs(i[0]-x)==abs(i[1]-y):
c = False
break
# no need for else at all
return c
Even better:
def p3(x,y,ls2):
for i in ls2:
if abs(i[0]-x)==abs(i[1]-y):
return False
# no need for else at all
return True
If I understand correctly your function, you could simplify it to the following:
def p3(x, y, ls2):
# if no list or list is empty
if not ls2: # the condition could be more convoluted if needed
return 'invalid input' # or return boolean depending on use case
for i in ls2:
# if condition is matched return immediately
if abs(i[0]-x)==abs(i[1]-y):
return False
# the condition was not matched in loop, return default True
return True
You could even simplify more using all that will stop prematurely if the condition is met:
def p3(x, y, ls2):
# if no list or list is empty
if not ls2: # the condition could be more convoluted if needed
return 'invalid input' # or return boolean depending on use case
return all(abs(i[0]-x)!=abs(i[1]-y) for i in ls2)
# or: return not any(abs(i[0]-x)==abs(i[1]-y) for i in ls2)
In general, if you instantiate a variable (namely c) inside of a for loop, it's best not to use that variable outside of that for loop.
The practical reason for this is that you can't be sure that for loop will run and so the variable might not get instantiated. The more high-level reason is to maintain a sense of scope in your code, or "what happens in the for loop, stays in the for loop", if you will.
So in your case, I would recommend instantiating c with a 'default' value (depending on what your logic is) before the for loop starts, so that even if the for loop runs 0 times, c still has a value.
Alternatively, this entire function could be implemented as
def p3(x, y, ls2):
return not any([abs(i[0]-x)==abs(i[1]-y) for i in ls2])

Logical operator Python

Probably a very basic question but I can not solve this.
That's my code:
if type(lines_r).__name__ == 'NoneType' or type(lines_l).__name__ == 'NoneType':
no_detected.append(i)
else: ...
Now, I don't want to use and/or operators because in this case I just want:
if the first condition is true <(lines_r) == Nonetype> so it'll be -No.detected- and, not connected to the other condition, I want to do the same thing for the other one (lines_l).
Because the 2 conditions could be not related in time (they are not at the same time both true or both false so I can't use AND + if I use OR then the condition is true if only one of the two is NoneType, and that's not what I want).
[The variables are str]
What's the best way to write this?
*EDIT
That's the things that I'm calculating
lines_r = cv2.HoughLinesP(Ske_conn_right[i],
rho = 1,
theta =np.pi/180,
threshold = 4,
minLineLength=2,
maxLineGap=7)
lines_l = cv2.HoughLinesP(Ske_conn_left[i],
rho = 1,
theta =np.pi/180,
threshold = 4,
minLineLength=2,
maxLineGap=7)
I'm doing detection of moving objects in a video. The results are arrays that could have some 0 values (in a simplistic way where objects are not detected).
lines_l or lines_r could result in a Nonetype obj
You can use instanceof to check if a value has a particular type, but here you should simply check if the value is None:
if lines_r is None or lines_l is None:
no_detected.append(i)
if both of your conditions are not related maybe you could use a if and else if statement
if type(lines_r).__name__ == 'NoneType':
no_detected.append(i)
elif type(lines_l).__name__ == 'NoneType':
no_detected.append(i)
else: ...
Then again that's the same thing as using an or statement, but it's just more similar to how you explained your logic
If you want the condition to be true only if one of line_r and line_l is None, you can test the variables first and then test if the results are not equal:
if (lines_r is None) != (lines_l is None):
no_detected.append(i)

Python does not allow multiple return() statements in ternary; possible alternative that is also aesthetically pleasing?

I am developing a text based RPG (graphics will be implemented later) and I am writing a method to determine whether a room a player is trying to go to exists or not. In this method I have multiple logic statements that determine what room the player is trying to get to based on the direction they enter and whether that "room" == 0 (my place holder for an empty space in the world/dungeon array). Although I can write a conventional logic statement for this:
if condition:
if otherCondition:
return(True)
else:
return(False)
a ternary is much more aestheticaly pleasing:
if condition:
return(True) if otherCondition else return(False)
But of course, that does not work. I am looking for something that functions as the conventional logic statement but is also "pleasing to the eye", like a ternary. In my code the logic statement is repeated four times, and the conventional logic statement would be displeasing to read.
I am using Python 3.5.1 on Windows 7.
The issue with your statement isn't the ternary part, it's the repeated return. Instead use:
if condition:
return True if otherCondition else False
Here, the result of the expression True if otherCondition else False is returned.
This could be written more concisely as:
if condition:
return bool(otherCondition)
Use just a single return with ternary statement:
return 'something' if someCondition else 'something else'
For you case is enough just :
if condition:
return otherCondition
# or if "otherCondition is not bool you can use: return bool(condition)
z = x if success else y
# this tallies z = success ? x : y, where success is a bool. Either True or False
Here the expression on the right returns x or y depending on if success evaluates to True or False respectively. As this is an expression it can be used with a return statement
return x if success else y
if condition:
return othercondition
Perhaps you should illustrate with an example, because it can be simplified to return the result of the other condition.
if condition:
return otherCondition
What ever happened to just:
if condition:
# tis very simple; if room is equal to 0, the operation is true, thus `True` will be returned
# otherwise `False`.. no mystery
return room == 0

when to use if vs elif in python

If I have a function with multiple conditional statements where every branch gets executed returns from the function. Should I use multiple if statements, or if/elif/else? For example, say I have a function:
def example(x):
if x > 0:
return 'positive'
if x < 0:
return 'negative'
return 'zero'
Is it better to write:
def example(x):
if x > 0:
return 'positive'
elif x < 0:
return 'negative'
else:
return 'zero'
Both have the same outcome, but is one more efficient or considered more idiomatic than the other?
Edit:
A couple of people have said that in the first example both if statements are always evaluated, which doesn't seem to be the case to me
for example if I run the code:
l = [1,2,3]
def test(a):
if a > 0:
return a
if a > 2:
l.append(4)
test(5)
l will still equal [1,2,3]
I'll expand out my comment to an answer.
In the case that all cases return, these are indeed equivalent. What becomes important in choosing between them is then what is more readable.
Your latter example uses the elif structure to explicitly state that the cases are mutually exclusive, rather than relying on the fact they are implicitly from the returns. This makes that information more obvious, and therefore the code easier to read, and less prone to errors.
Say, for example, someone decides there is another case:
def example(x):
if x > 0:
return 'positive'
if x == -15:
print("special case!")
if x < 0:
return 'negative'
return 'zero'
Suddenly, there is a potential bug if the user intended that case to be mutually exclusive (obviously, this doesn't make much sense given the example, but potentially could in a more realistic case). This ambiguity is removed if elifs are used and the behaviour is made visible to the person adding code at the level they are likely to be looking at when they add it.
If I were to come across your first code example, I would probably assume that the choice to use ifs rather than elifs implied the cases were not mutually exclusive, and so things like changing the value of x might be used to change which ifs execute (obviously in this case the intention is obvious and mutually exclusive, but again, we are talking about less obvious cases - and consistency is good, so even in a simple example when it is obvious, it's best to stick to one way).
Check this out to understand the difference:
>>> a = 2
>>> if a > 1: a = a+1
...
>>> if a > 2: a = a+1
...
>>> a
4
versus
>>> a = 2
>>> if a > 1: a = a+1
... elif a > 2: a = a+1
...
>>> a
3
The first case is equivalent to two distinct if's with empty else statements (or imagine else: pass); in the second case elif is part of the first if statement.
In some cases, elif is required for correct semantics. This is the case when the conditions are not mutually exclusive:
if x == 0: result = 0
elif y == 0: result = None
else: result = x / y
In some cases it is efficient because the interpreter doesn't need to check all conditions, which is the case in your example. If x is negative then why do you check the positive case? An elif in this case also makes code more readable as it clearly shows only a single branch will be executed.
In general (e.g. your example), you would always use an if..elif ladder to explicitly show the conditions are mutually-exclusive. It prevents ambiguity, bugs etc.
The only reason I can think of that you might ever not use elif and use if instead would be if the actions from the body of the preceding if statement (or previous elif statements) might have changed the condition so as to potentially make it no longer mutually exclusive. So it's no longer really a ladder, just separate concatenated if(..elif..else) blocks. (Leave an empty line between the separate blocks, for good style, and to prevent someone accidentally thinking it should have been elif and 'fixing' it)
Here's a contrived example, just to prove the point:
if total_cost>=10:
if give_shopper_a_random_discount():
print 'You have won a discount'
total_cost -= discount
candidate_prime = True
if total_cost<10:
print 'Spend more than $10 to enter our draw for a random discount'
You can see it's possible to hit both conditions, if the first if-block applies the discount, so then we also execute the second, which prints a message which would be confusing since our original total had been >=10.
An elif here would prevent that scenario.
But there could be other scenarios where we want the second block to run, even for that scenario.
if total_cost<10:
<some other action we should always take regardless of original undiscounted total_cost>
In regards to the edit portion of your question when you said:
"A couple of people have said that in the first example both if statements are always evaluated, which doesn't seem to be the case to me"
And then you provided this example:
l = [1,2,3]
def test(a):
if a > 0:
return a
if a > 2:
l.append(4)
test(5)
Yes indeed the list l will still equal [1,2,3] in this case, ONLY because you're RETURNING the result of running the block, because the return statement leads to exiting the function, which would result in the same thing if you used elif with the return statement.
Now try to use the print statement instead of the return one, you'll see that the 2nd if statement will execute just fine, and that 4 will indeed be appended to the list l using append.
Well.. now what if the first ifstatement changes the value of whatever is being evaluated in the 2nd if statement?
And yes that's another situation. For instance, say you have a variable x and you used if statement to evaluate a block of code that actually changed the x value.
Now, if you use another if statement that evaluates the same variable x will be wrong since you're considering x value to be the same as its initial one, while in fact it was changed after the first if was executed. Therefore your code will be wrong.
It happens pretty often, and sometimes you even want it explicitly to be changed. If that's how you want your code to behave, then yes you should use multiple if's which does the job well. Otherwise stick to elif.
In my example, the 1st if block is executed and changed the value of x, which lead to have the 2nd if evaluates a different x (since its value was changed).
That's where elif comes in handy to prevent such thing from happening, which is the primary benefit of using it.
The other secondary good benefit of using elif instead of multiple if's is to avoid confusion and better code readability.
Consider this For someone looking for a easy way:
>>> a = ['fb.com', 'tw.com', 'cat.com']
>>> for i in a:
... if 'fb' in i:
... pass
... if 'tw' in i:
... pass
... else:
... print(i)
output:
fb.com
cat.com
And
>>> a = ['fb.com', 'tw.com', 'cat.com']
>>> for i in a:
... if 'fb' in i:
... pass
... elif 'tw' in i:
... pass
... else:
... print(i)
Output:
cat.com
'If' checks for the first condition then searches for the elif or else, whereas using elif, after if, it goes on checking for all the elif condition and lastly going to else.
elif is a bit more efficient, and it's quite logical: with ifs the program has to evaluate each logical expression every time. In elifs though, it's not always so. However, in your example, this improvement would be very, very small, probably unnoticeable, as evaluating x > 0 is one of the cheapest operations.
When working with elifs it's also a good idea to think about the best order. Consider this example:
if (x-3)**3+(x+1)**2-6*x+4 > 0:
#do something 1
elif x < 0:
#do something 2
Here the program will have to evaluate the ugly expression every time! However, if we change the order:
if x < 0:
#do something 2
elif (x-3)**3+(x+1)**2-6*x+4 > 0:
#do something 1
Now the program will first check if x < 0 (cheap and simple) and only if it isn't, will it evaluate the more complicated expression (btw, this code doesn't make much sense, it's just a random example)
Also, what perreal said.

Function doesn't stop after "return(False)"

I am trying to write a function which is supposed to compare list structures (the values are indifferent). The problem is that I have two lists which are unequal but the function still returns True even though it actually goes into the else part. I don't understand why and what I did wrong. Here is my code:
def islist(p): #is p a list
return type(p)==type(list())
def ListeIsomorf(a,b):
if len(a)==len(b):
for i,j in zip(a,b):
if islist(i) and islist(j):
ListeIsomorf(i,j)
elif islist(i) or islist(j):
return(False)
return(True)
else:
print(a,"length from the list isn't equal",b)
return(False)
#example lists
ListeE = [[],[],[[]]]
ListeD = [[],[],[[]]]
ListeF = [[[],[],[[]]]]
ListeG = [[],[[]],[[]]]
ListeH = [1,[3]]
ListeI = [1,3]
#tests
print(ListeIsomorf(ListeD,ListeE)) # True
print(ListeIsomorf(ListeD,ListeF)) # False
print(ListeIsomorf(ListeD,ListeG)) # False
print(ListeIsomorf(ListeH,ListeI)) # False
So the problem only occurs with the third print(ListeIsomorf(ListeD,ListeG)) # False. It actually goes into the else part and does print the "length from the list isn't equal" but it doesn't stop and it doesn't give out the return(False). Am I missing something?
The problem is that when your function calls itself recursively:
ListeIsomorf(i,j)
it ignores the returned value.
Thus the comparisons that take place at the second level of recursion have no effect on what the top level returns.
Changing the above to:
if not ListeIsomorf(i,j):
return(False)
fixes the problem.

Categories