On 2022-02-03 at 15:07:22 +1100, Chris Angelico <ros...@gmail.com> wrote:
> On Thu, 3 Feb 2022 at 14:52, <2qdxy4rzwzuui...@potatochowder.com> wrote: > > > > On 2022-02-03 at 12:39:43 +1100, > > Cameron Simpson <c...@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. ;-) -- https://mail.python.org/mailman/listinfo/python-list