Waht do you think about my repeated_timer class

2QdxY4RzWzUUiLuE at potatochowder.com 2QdxY4RzWzUUiLuE at potatochowder.com
Wed Feb 2 23:27:24 EST 2022


On 2022-02-03 at 15:07:22 +1100,
Chris Angelico <rosuav at gmail.com> wrote:

> On Thu, 3 Feb 2022 at 14:52, <2QdxY4RzWzUUiLuE at potatochowder.com> wrote:
> >
> > On 2022-02-03 at 12:39:43 +1100,
> > Cameron Simpson <cs at cskk.id.au> wrote:
> >
> > > You have:
> > >
> > >     def _check_interval(self, interval):
> > >         if not type(interval) in [int, float]:
> > >             raise TypeError('{} is not numeric'.format(interval))
> > >
> > > This check is better written:
> > >
> > >     if not isinstance(interval, (int,float)):
> > >
> > > which handles subclasses of these types (but note that bool subclasses
> > > int :-) normally we don't care), or behaviourally:
> > >
> > >     try:
> > >         interval = float(interval)
> > >     except ValueError as e:
> > >         raise TypeError(
> > >             "cannot convert %s:%r to float: %s"
> > >             % (type(interval).__name__, interval, e)) from e
> > >
> > > which tries to convert to float and fails if that does not work, which
> > > supports classes with a __float__ method (these classes are rare, but
> > > decimal.Decimal is one example).
> >
> > I think this can be simplified for time intervals to the following:
> >
> >     if interval <= 0:
> >         raise ValueError(...)
> 
> That's checking something quite different, though. Casting to float
> will accept anything that can be, well, cast to float, but checking
> for less than or equal to zero demands that it already be some sort of
> number. It's debatable which check is more correct, but certainly this
> is not a simplification of the other code, it's a distinctly different
> validation.

Okay, "simplified" isn't quite the right word.  Given two examples (with
known deficiencies) and no actual use cases or specifications, I added a
third example, which I believed was simpler (and arguably better in one
or more ways, which I explained), than the others.

> > which accepts non-negative real values; throws ValueError for negative
> > real values; and TypeError for other stuff, including complex numbers
> > (pathological types notwithstanding).  One thing that doesn't work right
> > is NaNs, but I'm sure it's not the only code that acts weirdly when
> > faced with a NaM (curiously, Timer accepts a NaN, but the text I get
> > from help(Timer) in Python 3.10.2 is, well, broken).
> 
> Strange. The text I get in 3.11.0a1 is fine. But in any case, there's
> always the docs on the web.
> 
> https://docs.python.org/3/library/threading.html#timer-objects

help(Timer) is built into my REPL (and likely consumed by development
systems and IDEs everywhere).  No web necessary.

> > FWIW, I'd find some way to tell users the units (seconds, milliseconds,
> > fortnights, etc.) instead of making them wade through your code to find
> > the call to (and possibly the [broken] help text of) Timer.
> 
> In anything in Python, assume that the unit is seconds. With anything
> that accepts floats (where these can be distinguished from integers),
> assume the unit is seconds. If it accepts micro or nanoseconds, it'll
> almost certainly be called "high resolution timer" (unless it accepts
> two args, sec and us/ns, but that's pretty obvious), so you can
> generally exclude those too. The only real question is whether
> sleep(int) takes seconds or milliseconds, which isn't a problem here.
> 
> Citation: I've slept in many many programming languages and
> frameworks. Which sounds seriously weird, but you're all programmers,
> you know what I mean :)

I've slept in enough programming environments to know better than to
assume anything.  ;-)


More information about the Python-list mailing list