Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Description
Currently, the docstrings of TimerBase.add_callback and remove_callback read,
respectively
Register `func` to be called by timer when the event fires. Any additional arguments provided will be passed to `func`.
and
Remove `func` from list of callbacks. `args` and `kwargs` are optional and used to distinguish between copies of the same function registered to be called with different arguments.
AFAICT, the implementations match the behavior, but importantly, if called with
no args/kwargs, then remove_callback removes add instances where the function
has been added regardless of the presence of args/kwargs (hinted at by the
docstring, though possibly not obvious).
This means that if you have
def f(x=0): ...timer.add_callback(f)timer.add_callback(f, 1)
then you cannot remove the first callback without removing the second callback.
Compare with
def f(x=0): ...timer.add_callback(f, 0)timer.add_callback(f, 1)
where you can.
What can be changed to make things more consistent? On the one hand one could
say that remove_callback only removes complete matches (f, args, kwargs), i.e.remove_callback(f)
would undoadd_callback(f)
but notadd_callback(f, 1)
.
Alternatively, we can look into the stdlib's atexit.{register,unregister} which
needs to solve essentially the same semantics problem. There, the choice that
was made was for atexit.unregister toonly take the function as argument, and
remove all instances of that function regardless of args/kwargs; if one wants
to distinguish between them for removal one can always pass in a partial(f,
...) object; note that different instances of partial objects always compare
inequal even when the constructor is called twice with the same parameters.
(This is made simpler by atexit.register returning its first argument (for use
as a decorator), so one can dop = atexit.register(partial(f, ...))
to lateratexit.unregister(p)
.