This function outputs random values in a list. Although I was happy to craft this solution from a more complex version, and it looks really cool to me, I wonder if it is an example of clean code.
How can it be improved, and what are other ways to write it?
def random_time_values() -> List[int]:
''' Generates random [hours, minutes, seconds] '''
return [randint(*time) for time in [(0, 11), (0, 59), (0, 59)]]
1 Answer 1
What you've described and what you've written are two different things. You've described a function that outputs random times in a list, but it actually outputs a list of hour-minute tuple values randomly selected from a small, fixed set. Those can't both be true, so let's choose one - your description, of generating random times.
Why not:
- write a generator function that doesn't take an opinion on how many outputs you want; that way it can generate them lazily and the consumer can use e.g.
islice
- make truly random times, with random hour, minute, second and microsecond fields, rather than choosing from a set
This could be as simple as:
import datetime
import random
from itertools import islice
from typing import Iterator
def random_time_values() -> Iterator[datetime.time]:
base = datetime.datetime(1, 1, 1)
while True:
delta = datetime.timedelta(days=random.random())
yield (base + delta).time()
def demo(n: int = 25) -> None:
for t in islice(random_time_values(), n):
print(t)
if __name__ == '__main__':
demo()
22:09:36.696135
11:23:34.522248
00:09:56.177813
05:24:03.343375
22:25:56.346006
03:48:09.863071
20:48:27.955984
18:06:57.958131
00:15:05.198247
04:12:29.939244
09:50:25.152160
17:16:13.000451
10:51:36.054653
20:21:09.080549
02:00:15.132786
20:53:58.105197
08:25:13.088035
17:01:38.471288
04:14:28.054855
12:39:29.076931
07:13:03.665626
19:23:39.066675
15:46:20.652315
14:34:02.837399
13:34:33.400851
-
\$\begingroup\$ I didn't realise
datetime
values could be generated, I thought of the values as fractions of the circle: 12 parts and 60 parts of a whole. Thank you @Reinderien Although the function does return a list of three integer values, I understand now that these values are not explicit time values:>>> [randint(*time) for time in [(0, 11), (0, 59), (0, 59)]] # [7, 48, 19]
\$\endgroup\$Attila Vajda– Attila Vajda2023年11月17日 07:46:35 +00:00Commented Nov 17, 2023 at 7:46 -
\$\begingroup\$ After learning a bit about
datetime
this solution occured to me:random_time: datetime=datetime.time(randint(0, 23), randint(0, 59), randint(0, 59))
\$\endgroup\$Attila Vajda– Attila Vajda2023年11月19日 19:25:12 +00:00Commented Nov 19, 2023 at 19:25 -
1\$\begingroup\$ That's both more complicated and not as random, since it doesn't set microseconds. \$\endgroup\$Reinderien– Reinderien2023年11月19日 19:30:48 +00:00Commented Nov 19, 2023 at 19:30
user_time = input_field.get() % 12
. I think for hour hands angles, only 12 hour fractions are relevant. The user can input 24 hours and the modulo makes it into 12 hour range before comparing values. \$\endgroup\$