Infinite loop in class - python

I keep getting an infinite loop in this class and this time it's definitely coming from .ExNote() but I have no idea why. I've simplified it down so here you go:
class Note():
x=[0]
y=[0]
def __init__(self, Num, staff, note, notetype):
self.staff = staff
self.note = note
self.notetype = notetype
self.Num=Num
def ExNote(self):
screen.blit(self.notetype, (self.x[self.Num], self.y[self.Num]))
print('exnote')
going = True
while going:
screen.fill(white)
Note(0, '0R', '40', EthnoteIMG).ExNote()
returrns
exnote
exnote
exnote.....
Why doesn't it stop after doing the function once?

"while going:" is a loop. It needs to be set to False inside the loop to stop it. With just the code you've shown, the while loop isn't needed and could be removed altogether. You said you're only showing a portion of the code, so I'll leave it up to you to decide when the loop should stop.
class Note():
x=[0]
y=[0]
def __init__(self, Num, staff, note, notetype):
self.staff = staff
self.note = note
self.notetype = notetype
self.Num=Num
def ExNote(self):
screen.blit(self.notetype, (self.x[self.Num], self.y[self.Num]))
print('exnote')
going = True
while going:
screen.fill(white)
Note(0, '0R', '40', EthnoteIMG).ExNote()
if <your stop condition>:
going = False # You need to set going to False inside your loop to get it to stop
OR
going = <some function that returns false when appropriate>

Please insert a break function at the end of your code
while True:
Bla blabla
Blablabla
break
That should kill it

Related

How to return to stop multiple levels up

I want to be able to return to stop the parent function inside a function like this:
def FunctionBeingRan():
#Running Script
def stop():
return #return to stop the parent function
FunctionBeingRan().stop
Anyone know how to do this
you can return some number represent stop such as -1 and add a check statement to it .
def FunctionBeingRan():
#Running Script
def stop():
return #return to stop the parent function
if stop() == -1:
return
as python doesn't have goto statement, but there do have some nice packages that implement it
from goto import with_goto
#with_goto
def fun1(start, stop):
label .begin
# your code here
def stop():
# stop logical here
goto .end
# your remaining code here
label .end
return result
but it is dangerous for making code hard to read.
The best way is refact your logic.

Don't understand why this while doesn't stop

I have a selenium bot doing actions on a social network. I would like it to stop after he does a certain number of actions (10 is for the example). I initialize variables this way:
def __init__(self):
self.browser = webdriver.Firefox()
self.counter_var = int(0)
self.max_var = int(10)
This is the part performing and counting actions:
def action(self, accounts):
for account in accounts[9:]:
try:
self.browser.get(account)
time.sleep(5)
like_button = self.browser.find_element_by_xpath(
u'//button[contains(#class, "Heart")]').click()
self.count_actions()
print(self.counter_var)
except selenium.common.exceptions.NoSuchElementException:
break
def count_actions(self):
self.counter_var += 1
And this is the loop I've tried to make into main:
while self.counter_var < self.max_var:
searched_category = random.choice(pool_categories)
accounts = self.load_category(searched_category)
self.action(accounts)
However the bot never stops, even when counter_var reaches 10.
Do you know how to correct it?
Currently it's impossible to give a concrete answer to your question, due to the lack of code given, but it looks like the problem is because the action() method doesn't check self.counter_var while the for loop within it is executing.
Something like the follow might work. Adding yield to the action() method turns it into a generator function, which makes it iterable. When that is done it will effectively "pause" at that point each iteration of its for loop, and would allow the caller to inspect the current value of self.counter_var (or anything else it wanted to do each iteration).
Here's what I'm suggesting with a few explanatory comments:
class Class:
def action(self, accounts):
for account in accounts[9:]:
try:
self.browser.get(account)
time.sleep(5)
like_button = self.browser.find_element_by_xpath(
u'//button[contains(#class, "Heart")]').click()
self.count_actions()
print(self.counter_var)
yield # Added.
except selenium.common.exceptions.NoSuchElementException:
break
def count_actions(self):
self.counter_var += 1
def main(self):
while True:
searched_category = random.choice(pool_categories)
accounts = self.load_category(searched_category)
for _ in self.action(accounts): # Iterate through account checks.
if self.counter_var < self.max_var: # Too many actions?
break

Best way to run code once within while loops?

I'm writing a text-based RPG for a class, and am stuck on a code predicament...
from tkinter import *
...
runOnce = False
nextRun = False
"""Main Loop"""
while True:
#New Game initialize
if you.rName == None and runOnce == False:
log("What is your name, adventurer?", eventLog)
runOnce = True
if you.rName != None and nextRun == False:
log(f'What is your profession, {you.rName}?', eventLog)
nextRun = True
#keypresses
playerInput.bind("<Return>", keyPress)
playerInput.bind("<FocusIn>", focusIn)
top.update()
top.update_idletasks()
What I have currently works, but there are a ton more if-statement type situations that need responses before continuing to the next statement. The loop is to continuously update the GUI as the game is run.
How can I code the something that needs a response once within a while loop efficiently?
Seeing the clarification, I agree with the comments these type of actions shouldn't belong in the loop. These should be all data that are collected prior to the main game loop.
If you're looping through these to validate for inputs, you can have separate loops instead:
while not you.name:
you.name = input('Enter name: ')
# some additional validation text if necessary...
while not you.job:
you.job = input('Enter job: ')
# some additional validation text if necessary...
while True:
# main game loop requiring you.name, you.job
Another approach is a bit contrived. You can pre-define these functions before your mainloop and create a RunOnce class to only execute these functions once:
class RunOnce(object):
def __init__(self, func):
self.func = func
self.ran = False
def __call__(self):
if not self.ran:
self.func()
self.ran = True
# once the function has been called,
# flip self.ran so it won't fire again.
# Decorate your functions with this special class
#RunOnce
def get_name():
you.name = input('Enter Name: ')
#RunOnce
def get_job():
you.job = input('Enter Job: ')
And then when you are in the main game loop:
while True:
get_name() # this will run once
get_job() # this too will run once
get_name() # this won't run anymore
get_job() # this neither.
The benefit of this approach is it gives you the flexibility to re-run the function if necessary:
get_name() # get_name.ran becomes True
get_name.ran = False # reset the flag
get_name() # this will run again.
I'd still say it's much better to just restructure your code so that things that only need to be captured once stay outside the main loop.
Try checking your parameters for null before using them. If you're looking for user input you can do this:
userInput = None
while True:
userInput = input("Do the thing only once") if userInput is None else userInput
...

Creating a Stopwatch progam for Python 3.3 only in IDLE

I have an assignment where I need to create a stopwatch, but only for IDLE. Here's what I have so far, I'm not sure how to convert the times to normal time.
import time
start = 0
def stopwatch():
while True:
command = input("Type: start, stop, reset, or quit: \n")
if (command == "quit"):
break
elif (command == "start"):
start = time.time()
print(start)
stopwatch2()
elif (command == "stop"):
stopwatch()
elif (command == "reset'"):
stopwatch()
else :
break
def stopwatch2():
while True:
command = input("Type: stop, reset, or quit: \n")
if (command == "quit"):
break
elif (command == "stop"):
total = time.time() - start
print(total)
stopwatch()
elif (command == "reset'"):
stopwatch()
else:
break
stopwatch()
Thanks for your help!
You can use datetime.timedelta():
import datetime
print(datetime.timedelta(seconds=total))
For example:
In [10]: print datetime.timedelta(seconds=10000000)
115 days, 17:46:40
Think of it like this... Idle is really no different than coding in the interactive python interpreter which I do all the time (well, I use ipython).
Think of your stopwatch like an object. What functionality does it have? Things like start, stop, reset.
This may not be the most efficient way to solve the problem but here is what I would do.
>>> import time
>>> class StopwatchException:
pass
>>> class IsRunningException(StopwatchException):
pass
>>> class NotRunningException(StopwatchException):
pass
>>> class Stopwatch():
def __init__(self):
self._times = []
self._is_running = False
def start(self):
if self._is_running:
raise IsRunningException
self._is_running = True
tracker = {
'start': time.time(),
'stop': None,
}
self._times.append(tracker)
def stop(self):
if not self._is_running:
raise NotRunningException
tracker = self._times[-1]
# the dict is mutable, and tracker is a shallow copy
tracker['stop'] = time.time()
#print(self._times[-1])
self._is_running = False
def reset(self):
if self._is_running:
raise IsRunningException
self._times = []
def total(self):
if self._is_running:
raise IsRunningException
total = 0.0
for t in self._times:
total += t['stop'] - t['start']
return total
>>> s = Stopwatch()
>>> s.start()
>>> s.stop()
>>> s.total()
6.499619960784912
>>> s.reset()
>>> s.total()
0.0
To me, anytime you want to model a real world object or "thing", OOP makes the most sense. Heres a simple argument for each element of the program:
Classes
StopwatchException
Base exception class for the stopwatch class.
IsRunningException
Raised if the stopwatch is running when it should be stopped.
NotRunningException
Raised if the stopwatch is not running when it should be.
Stopwatch
This represents the actual stopwatch.
Stopwatch Class
init
A basic stopwatch class really only needs to instance variables. A variable that stores each start/stop time (allows them to be computed later) and a variable that stores the "state" of the stopwatch (on/off or running/stopped).
start
First we need to make sure the stopwatch isn't already running.
Then we need to set it's state to running and store the time in self._times.
I chose to use a local variable and store each time pair as a dictionary with the keys 'start' and 'stop'. I chose a dictionary because it is mutable. You could also have a list with index 0 being the start time and index 1 being the stop time. You cannot use a tuple for this since tuples are immutable.
Also, the "temporary" variable is not necessary but I used it for readability.
stop
First we need to make sure the stopwatch is actually running.
Then we set the state as 'stopped' (using our boolean self._is_running) and store our stop time, similar to what we did with start. I think it doesn't matter whether you set the boolean at the beginning or the end, although I chose to set it at the beginning of the start function and the end of the stop function so that the times would not include the time needed to update a boolean variable (even though it's a trivial task, it could be much more complex in more complex programs).
reset
Make sure the stopwatch isn't running
Set self._times to be an empty list.
total
Make sure the stopwatch isn't running.
Optional: You can stop the stopwatch here if it's running, but I prefer to raise an exception.
Iterate through each list item in self._times and calculate the difference between stop and start.

Modifying a function from another in python

For an online course in python, I'm making a basic text-based adventure game in python.
Right now, I have a rudimentary inventory system that works through booleans for if the user has an object or not, and integers for limited items, such as ammo and whatnot.
Here is the code for the inventory system
def Inventory(self): #The inventory for the game. I don't know how to program it properly, so this is my testing ground.
#This will hold the boolean values to if the player has the items or not. Another will be used to show the user the items
street_clothes = False
pistol = False
ammo = 0
phone = False
And this is the code where I am trying to modify the inventory function above
#Eric's apartment
def Eric_Apartment(self):
print "type in grab your gun"
action = raw_input("> ")
if action == "grab":
self.Inventory(CR97) = True
# self.CR97_ammo += 15
# print CR97_ammo
# print self.CR97_ammo
exit(1)
Attempting to run this program gets me this error:
python ex43.py
File "ex43.py", line 78
self.Inventory(CR97) = True
SyntaxError: can't assign to function call
Is there something else I'm supposed to do? I'm very new to python, and this is my first project on my own.
Here is the entire code, for reference
from sys import exit #allows the program to use the exit(1) code
from random import randint #allows the program to use a random number
class Game(object):
#quotes that pop up if the person dies, and also defines the start and self variables
def __init__(self, start):
self.quips = [
"You lose!"
]
self.start = start
def Inventory(self): #The inventory for the game.
#This will hold the boolean values to if the player has the items or not.
street_clothes = False
pistol = False
ammo = 0
phone = False
#this function launches the game, and helps with the room transfer
def play(self):
next = self.start
while True:
print "\n---------"
room = getattr(self, next)
next = room( )
#if the user dies, or fails at the game, this is the function that is ran
def death(self):
print self.quips[randint(0, len(self.quips)-1)]
exit(1)
#Welcome screen to the game
def welcome_screen(self):
print " place holder"
return 'intro_screen'
#Intro screen to the game
def intro_screen(self):
print "place holder"
action = raw_input("> Press any key to continue ")
return 'Eric_Apartment'
#Eric's apartment
def Eric_Apartment(self):
print "type in grab your gun"
action = raw_input("> ")
if action == "grab":
self.Inventory(CR97) = True
# self.CR97_ammo += 15
# print CR97_ammo
# print self.CR97_ammo
exit(1)
a_game = Game("welcome_screen")
a_game.play()
That's an amazingly perverse way to go about it. Why are you using a function to store data?
Just have a player object, with an inventory array.
I'd recommend using objects to model items too. Good use for for a class hierarchy. COuld have a base Item, with Subclasses SingleItem and StackableItem, etc.
Instead of using a function, try using a class -
class Player:
def __init__(self):
self.street_clothes = False
self.pistol = False
self.ammo = 0
self.phone = False
def give_street_clothes(self):
self.street_clothes = True
# etc
But personally, instead of using each item as a boolean, I'd use a list of items:
class Player:
def __init__(self):
self.inventory = []
# add code for ammo/pistol
def has_item(self, item):
return item in self.inventory
def give_item(self, item):
self.inventory.add(item)
def remove_item(self, item):
self.inventory.remove(item)
# etc

Categories

Resources