Home > Blockchain >  Understanding zip functions
Understanding zip functions

Time:09-27

I am new to learning python, I have been using source material for inspiration on how to code an alarm clock. I was wondering if anyone could explain a couple of the lines for me?

print("Set a time for the alarm (Ex. 06:30 or 18:30:00)")

while True:

    alarm_input = input(">> ")

    try:

        alarm_time = [int(n) for n in alarm_input.split(":")]

        if check_alarm_input(alarm_time):

            break

        else:

            raise ValueError

    except ValueError:

        print("ERROR: Enter time in HH:MM or HH:MM:SS format")

# Convert the alarm time from [H:M] or [H:M:S] to seconds

seconds_hms = [3600, 60, 1]  # Number of seconds in an Hour, Minute, and Second

alarm_seconds = sum(
    [a*b for a, b in zip(seconds_hms[:len(alarm_time)], alarm_time)])

The while True is just referring to the check_alarm_input function I have which makes sure that the input is an actual time.

I am mainly confused by the line converting the alarm time to seconds,

I am not sure what a and b is and what is the purpose of the colon in:

zip(seconds_hms[:len(alarm_time)]

Any help appreciated!

CodePudding user response:

Let's say the user inputs the string "1:20:45".

Then, the alarm_time list will be [1, 20, 45].

The seconds_hms will of course always be [3600, 60, 1].

Next, let's look at seconds_hms[:len(alarm_time)].

len(alarm_time) is 3 in this example, so this is equivalent to seconds_hms[:3].

This is a slicing operation, which slices the seconds_hms list from index 0 implicitly, and slices up to (but not including) index 3, which would be the fourth item, and then returns the new sliced list. In this case, the sliced list is the same as the unsliced list [3600, 60, 1]. If the user had entered the string "1:20", then len(alarm_time) would be 2, which means the slice would be from 0 to 2 (not including index 2), which means the sliced list would be [3600, 60].

Going back to my original example, what we have now is equivalent to zip([3600, 60, 1], [1, 20, 45]). zip will yield tuples that contain the next item from each iterable. So, the first tuple will be (3600, 1), the second tuple will be (60, 20), and the third tuple will be (1, 45).

These tuples are then unpacked into a and b in the list-comprehension. So, during the first iteration, a will be 3600 and b will be 1. During the second iteration, a will be 60 and b will be 20. In the third iteration a will be 1 and b will be 45.

Essentially, the list comprehension is constructing a list that looks like: [3600 * 1, 60 * 20, 1 * 45].

Which is equivalent to: [3600, 1200, 45].

You then take the sum of that list to get 4845 seconds.

If the user had entered 1:20 instead of 1:20:45, like I mentioned earlier, then len(alarm_time) would be 2 instead of 3. This means the sliced list we pass to zip would be shorter:

zip([3600, 60], [1, 20])

Which means zip would only yield two tuples, which means our list-comprehension would only have two iterations, and the constructed list would only have two values:

[3600 * 1, 60 * 20].

That being said, the slicing operationg is not required, since zip will stop yielding tuples as soon as one of its iterables is exhausted. That means you can simply write: zip(seconds_hms, alarm_time), and your script should behave exactly the same way.

  • Related