How to break out of a for loop using a function? - python

I'm running an if action defined in a function on a list of elements using a for loop. There is a secondary action within the first action. I want the for loop to stop once the action is successful the first time. Below is sample code to demonstrate:
my_list = [99, 101, 200, 5, 10, 20, 40]
def action(x):
if x >= 100:
print('It is finished')
over_100 = True
return over_100
def action2(x):
x += 1
action(x)
over_100 = False
for number in my_list:
action2(number)
if over_100:
break
I want the for loop to stop at the first instance of >=100. For example, it should add 1 to 99 (first element of the list) and then stop everything. Instead, it is printing "It is finished" 3x because it loops through the whole list.

You can make the function return a value and check the value in the loop. And you can use break to break out of the loop.
list_of_scopes = [scope1, scope2, scope3, etc.)
def action_function():
return 'TEST' in xxxxx
for scope in list_of_scopes:
found = action_function()
if found:
break
As of Python 3.8 you could even use the walrus operator which makes for more readable code:
for scope in list_of_scopes:
if found := action_function():
# optionally do something with `found`
break

A totally different approach to show what I meant in my comment on the question:
from contexlib import suppress
class StopProcessing(StopIteration):
pass
def action_function(param):
if 'TEST' in param:
print('TEST is found!')
raise StopProcessing
with suppress(StopProcessing):
for scope in list_of_scopes:
action_function()

I think you are looking for global.
Global tells your function's scope to not create a new variable over_100 but instead re-use an over_100 that was declared in a higher scope.
I do prefer the other answers that return a value instead of polluting global scope. Whatever works!
my_list = [99, 101, 200, 5, 10, 20, 40]
over_100 = False
def action(x):
global over_100
if x >= 100:
print('It is finished')
over_100 = True
def action2(x):
global over_100
x += 1
action(x)
if over_100:
return
# here is more work for action2 that you skip when over_100
for number in my_list:
action2(number)
if over_100:
break
Output:
It is finished

list_of_scopes = [scope1, scope2, scope3, etc.)
def action_function(param):
found = False
if 'TEST' in param:
print('TEST is found!')
found = True
return found
for scope in list_of_scopes:
result = action_function(scope) # or whatever parameter
if result:
break

Related

Access an iterator in 'for' loop, before the loop

I am trying to access an iterator 'obj' before the 'for' loop like this
class MyClass:
CLASS_CONST1 = 'some_rand_const'
def __init__(self, type, age):
self.type = type
self.age = age
var1 = 5
age = 7
# # I tried to individually add the following lines here, none of them work
# obj = MyClass
# obj = MyClass()
condition = obj.type == MyClass.CLASS_CONST1
if var1 > 10:
condition = obj.type == MyClass.CLASS_CONST1 and obj.age == age
list_of_objects = [MyClass('rand1', 'rand2'), MyClass('rand1', 'rand2'), MyClass('rand1', 'rand2')]
for obj in list_of_objects:
if condition:
# do some stuff
pass
The issue is that it is accessed before it is defined (it gets defined in the for loop). And I dont want introduce the condition lines inside the 'for' loop because the lines would be executed in every iteration, and there is no need for that.
The idea is that all this goes into a function and 'var1' and 'age' are arguments of the function.
obj = MyClass just assigns the class object (not instance) to another variable. obj = MyClass() will throw an error because you haven't provided values for type and age which are required in __init__. Did you try obj = MyClass(var1, age) ? You did it later for list_of_objects.
Anyway, you've tried to create condition as a variable that is supposed to apply itself during the iteration. That's not how Python works. It's given a static value when it's evaluated the one time. To have it apply to all objects, have condition as a function which either take the object or the two variables type and var as parameters and then return the result of the check:
var1 = 5
age = 7
def condition(obj):
# will return the True/False result of the check below
return obj.type == MyClass.CLASS_CONST1 and obj.age == age
for obj in list_of_objects:
if condition(obj): # call the function with that object
# do some stuff
pass
From your code, it's unclear what you wanted in condition. Maybe it was this?
var1 = 5 # or put these inside `condition` so they are local
age = 7 # to condition and not globals.
# Or pass them in as parameters and modify `condition` to accept
# the additional params
def condition(obj):
result = obj.type == MyClass.CLASS_CONST1
if result and var1 > 10:
# don't re-check `obj.type == MyClass.CLASS_CONST1`
result = obj.age == age
return result
You declare condition as a simple boolean variable, while its value has to depend on the current values of obj. You could use a bunch of functions and assign condition to the relevant one, or as you conditions are simple, you could use lambdas:
condition = obj.type == MyClass.CLASS_CONST1
if var1 > 10:
condition = lambda obj: obj.type == MyClass.CLASS_CONST1 and obj.age == age
else:
condition = lambda obj: obj.type == MyClass.CLASS_CONST1
and then use it as a variable function:
for obj in list_of_objects:
if condition(obj):
# do some stuff
pass

How can I check if the current string and previous string in Python code?

In this code I want to compare the previous message with the current message. So I created a variable to save the previous message. I wanted to create it as a static variable then manipulate it inside the code. but the outside the x function if I declare the variable it shows an error.
flag = 1
previousMessage = "abc"
def x():
do_something
currentMessage = m #got a string from code
if(currentMessage==previousMessage):
#shows error in flag and previousMessgae
#says create parameter of previousMessage and flag
flag=0
return
else:
do_something
previousNews=currentNews
flag=1
return
def call():
while True:
if(flag==1)
x()
time.sleep(60)
elsif(flag==0)
time.sleep(60) **strong text**
call()
Not sure if this is what you need. Try adding global before flag and previousMessage to make that variable a global variable.

How to loop 2 functions in python?

I have 2 functions that I need to call each other based on user settings. That is, if a user has repeat turned on it just needs to keep going until manually stopped, which I have a button for. How can I do this without causing an infinite loop error that crashes the program?
def T1_Timer(list):
msg = list[0]
global t1
T1_List = list
t1 = threading.Timer(MultiTimer2Settings.T1_Time, msg)
while t1.is_alive():
if not t1.is_alive():
return
else:
time.sleep(1)
Parent.SendTwitchMessage(msg)
T1_List.pop(0)
return T1_List
def DoRun1():
T1_List1 = []
T1_List2 = []
while not StopPressed:
T1_List1 = CheckList1(T1_List2)
T1_List2 = T1_Timer(T1_List1)
return
StopPressed = False
def StopButton():
global StopPressed
StopPressed = True
return
def CheckList1(T1_List=[]):
global t1
t1 = threading.Timer(MultiTimer2Settings.T1_Time, "")
if not t1.is_alive() and len(T1_List) <= 0:
if MultiTimer2Settings.T1M1_Enabled:
T1_List.append(MultiTimer2Settings.T1M1)
if MultiTimer2Settings.T1M2_Enabled:
T1_List.append(MultiTimer2Settings.T1M2)
if MultiTimer2Settings.T1M3_Enabled:
T1_List.append(MultiTimer2Settings.T1M3)
if MultiTimer2Settings.T1M4_Enabled:
T1_List.append(MultiTimer2Settings.T1M4)
if MultiTimer2Settings.T1M5_Enabled:
T1_List.append(MultiTimer2Settings.T1M5)
return T1_List
Just use a while loop:
stopButtonPressed = False
var1 = <initial value>
while not stopButtonPressed:
var2 = function1(var1)
var1 = function2(var2)
Instead of each function calling the other, they should return the value that they would pass to the other function. You can then put these in variables and pass them in the successive calls.
something like this
Break = 0
Function1():
test = 12
print test
return
Function1():
test1 = 13
print test2
return
while Break < 15:
Break += 1
Function1()
Function2()
calling another function using one function will not be in the loop therefore doing this is the simplest option
try running it!

Decrementing Function Arguments (PYTHON)

I'm calling functions similar to those that follow, inside a loop:
def bigAnim(tick,firstRun):
smallAnim(x,y,duration)
#more anims and logic...
def smallAnim(x, y,duration):
duration -= 1
if duration != 0:
Anim.blit(screen,(x ,y))
Anim.play()
else:
Anim.stop()
loopedOnce = True
return loopedOnce
Now say I were to call the smallAnim inside the big anim as follows:
def bigAnim(tick,firstRun):
smallAnim(0,50,5)
smallAnim is now being called indefinitely, as duration will never go lower than 4 (being reset to 5 every time it's called in the loop). What would be the best way to solve this problem?
You need to do the counting in bigAnim and only call smallAnim() when the value is greater than zero.
Or you can return the current duration:
def bigAnim(tick,firstRun):
duration = smallAnim(x,y,duration)
#more anims and logic...
def smallAnim(x, y, duration):
duration -= 1
if duration > 0:
Anim.blit(screen,(x ,y))
Anim.play()
return duration
Your underlying problem is Python does pass the references to the variables, but integers are immutable.
This is a little easier to understand with strings:
The function
def foo(s):
s = " world"
will only modify s local to the function if you call foo("hello"). The typical pattern you'll see instead is:
def foo(s):
return s + " world"
And then ... print foo("hello")

Why won't a global variable change when assigning to it in a function?

I'm making a game in python, and I have some code set up as such:
istouching = False
death = True
def checkdead():
if istouching:
print "Is touching"
death = True
while death is False:
print death
# game logic
I know the game logic is working, because "Is touching" prints, but then when I print out the value of death, it remains false.
use global to change global variables inside a function, otherwise death=True inside checkdead() will actually define a new local variable.
def checkdead():
global death
if istouching == True: #use == here for comparison
print "Is touching"
death = True
Make checkdead return a value:
def checkdead():
if istouching:
print "Is touching"
return True
death = checkdead()
You could also use global, as #AshwiniChaudhar shows, but I think it is preferable to write functions that return values instead of functions that modify globals, since such functions can be unit-tested more easily, and it makes explicit what external variables are changed.
PS. if istouching = True should have resulted in a SyntaxError since you can not make a variable assignment inside a conditional expression.
Instead, use
if istouching:
That's scope-related.
death = False
def f():
death = True # Here python doesn't now death, so it creates a new, different variable
f()
print(death) # False
death = False
def f():
global death
death = True
f()
print(death) # True

Categories