1

I'm very new to python, and I'm trying to make a sort of idle game. I'm having a little bit of trouble optimizing a function I wrote that flashes "ON" and then "OFF" every time a second passes.

While it works fine, it checks to see if a second has passed so many times that it peaks my CPU. The code is below:

import time
def timer():
  oldtime = int(time.time())
  #grabs the time on initiation
  while True:
    if oldtime < int(time.time()):
      return 'ON'
      #flashes on
      return 'OFF'
      #makes everything that checks if it's on only proc once
      oldtime += int(time.time()) - oldtime
      #makes oldtime advance one second ahead of time.time(),
      #even if more than one second passes at a time

timer()
while timer() == "ON":
  print('lorem ipsum')
#output: lorem ipsum every second and a peaking CPU

How would one go about optimizing something like this?

amaramist_
  • 11
  • 2
  • 2
    You don't seem to quite understand what `return` does. Everything in your function after `return 'ON'` is unreachable and completely irrelevant; returning *ends the function*. – jasonharper Feb 14 '23 at 21:06
  • You _could_ use `yield` instead of `return`; put a sleep inside your timer function, and then `for value in timer(): if value == 'ON': ...` would be on the road to being meaningful/useful, though if you're not careful to adjust your sleep durations to compensate for differences between requested and actual delays (and time spent outside the sleep) you get drift. – Charles Duffy Feb 14 '23 at 23:51

2 Answers2

2

Here I have written a while loop that calls a function that will check the previous state of a variable and depending on whether it was ON or OFF it will sleep for 1 second and change to the other state.

import time
def repeat():
    isOn = True
    if(isOn):
       time.sleep(1)
       isOn = False
       return 'OFF'
    if(isOn != True):
       time.sleep(1)
       isOn = True
       return 'ON'
 while True:
 #You could always take the return value of repeat() to do something else 
 #in your code
     repeat()
Charles
  • 79
  • 2
  • Note that `time.sleep(1)` will cause the loop to run slightly _slower_ than once per second on average, because you're waiting a second without taking into account how much time was spent running non-sleep code, waiting for the operating system to context-switch the process back to foreground, etc. – Charles Duffy Feb 14 '23 at 22:27
  • (See folks talking about "drift" on the linked duplicate) – Charles Duffy Feb 14 '23 at 22:33
  • The other, bigger issue here is that `isOn` isn't static: every time your function starts it's always reset to `True`, so `if(isOn != True)` will never be run. – Charles Duffy Feb 14 '23 at 23:50
  • Ok, is there a way to make the variable static? I know in Java I need the static keyword But I didn't know they existed in python. From what I saw it looks like you need a class. Also when I ran it, I was able to print both answers. – Charles Feb 15 '23 at 00:25
  • A class is the _better_ way, but it's not the _only_ way; you can use a global, f/e. – Charles Duffy Feb 15 '23 at 13:46
0

I'm not sure if this is actually what you want as I feel like you are likely looking to do "something else" in the pause.

However, looking at your code, I think this will give you the result you are currently working towards. The key to not using up resources is to sleep()

import time

def timer():
    time.sleep(1)
    return ["On ", "Off"][int(time.time() % 2)]

while True:
    print(timer(), end="\r", flush=True)
JonSG
  • 10,542
  • 2
  • 25
  • 36