Timer with interval function I've been tasked with writing a function that executes a passed function every interval, passed to the function by the user. Below is the code, and how to call it:
import time
from typing import Callable

last_milliseconds: int = 0
def set_timer(interval: int, function: Callable) -&gt; bool:
    global last_milliseconds
    milliseconds: int = int(round(time.time() * 1000))
    done: bool = (milliseconds - last_milliseconds) &gt;= interval
    if done:
        function()
        last_milliseconds = milliseconds

Called by:
p: Callable = lambda: print(&quot;set_timer called.&quot;)

while True:
    set_timer(1000, p)

Is there a better way to go about this? I'm unsure with the use of the global variable, and the function must be called in an infinite loop structure in order to work. Any and all feedback is accepted and appreciated.
First of all, your function doesn't return anything and so you can remove -&gt; bool since it only creates confusion. You can either use -&gt; None or use nothing at all. Still related to type annotations, I find it kinda hard to read your code with annotations everywhere. This is subjective and it's just my personal preference but I usually tend to use type annotations only when dealing with function / class definitions and their arguments.
For example, milliseconds: int = int(round(time.time() * 1000)) it's obviously going to be an integer since we can see the cast to int().
More, round() already returns an int in your case so that can be removed as well. The done variable can also be omitted and added directly to the condition itself:
def set_timer(interval: int, function: Callable) -&gt; None:
    global last_milliseconds
    milliseconds = round(time.time() * 1000)
    
    if milliseconds - last_milliseconds &gt;= interval:
        function()
        last_milliseconds = milliseconds

You can also remove the parentheses from your condition since - has a higher precedence than &gt;=.

Strictly speaking about the implementation, if you're not tied to using a function and want to get rid of the usage of global, I'd use a class:
from time import time
from typing import Callable


class Timer:
    def __init__(self):
        self.last_milliseconds = 0

    def set(self, interval: int, function: Callable) -&gt; None:
        milliseconds = round(time() * 1000)

        if milliseconds - self.last_milliseconds &gt;= interval:
            function()
            self.last_milliseconds = milliseconds

Which can be used like this:
def main():
    timer = Timer()
    while True:
        timer.set(1000, lambda: print(&quot;set_timer called.&quot;))


main()

Or, even better, you can have a static class if your workflow allows it:
class StaticTimer:
    last_milliseconds = 0

    @classmethod
    def set(cls, interval: int, function: Callable) -&gt; None:
        milliseconds = round(time() * 1000)

        if milliseconds - cls.last_milliseconds &gt;= interval:
            function()
            cls.last_milliseconds = milliseconds

Which you'd call like this:
def main():
    while True:
        StaticTimer.set(1000, lambda: print(&quot;set_timer called.&quot;))


main()

The difference between the two classes is that you can't have multiple of the latter because of the class attribute and @classmethod. So even if you made multiple instance of the class, they'd all share that value.