Search code examples
pythonlistlist-comprehensionpython-assignment-expression

Walrus operator in list comprehensions (python)


When coding I really like to use list comprehensions to transform data and I try to avoid for loops. Now I discovered that the walrus operator can be really handy for this, but when I try to use it in my code it doesn't seem to work. I've got the following code and want to transform the strings containing data about the timestamps into datetime objects in one easy line, but I get an syntax error and I am not sure what the right syntax would be, does anyone know what I did wrong?

from datetime import datetime

timestamps = ['30:02:17:36',
              '26:07:44:25','25:19:30:38','25:07:40:47','24:18:29:05','24:06:13:15','23:17:36:39',
              '23:00:14:52','22:07:04:33','21:15:42:20','21:04:27:53',
              '20:12:09:22','19:21:46:25']

timestamps_dt = [
    datetime(days=day,hours=hour,minutes=mins,seconds=sec) 
    for i in timestamps
    day,hour,mins,sec := i.split(':')
] 


Solution

  • Since Walrus operator does not support values unpacking, the operation

    day,hour,mins,sec := i.split(':')

    is invalid.

    Walrus operator is recommended to be used mostly in logic comparison, especially when you need to reuse a variable in comparison. Therefore, I would argue that for this case, a simple datetime.strptime() would be better for this case.

    If you must use walrus comparison in your list comprehension, you may do

    from datetime import datetime
    
    timestamps = ['30:02:17:36',
                  '26:07:44:25','25:19:30:38','25:07:40:47','24:18:29:05','24:06:13:15','23:17:36:39',
                  '23:00:14:52','22:07:04:33','21:15:42:20','21:04:27:53',
                  '20:12:09:22','19:21:46:25']
    
    timestamps_dt = [
        datetime(2020,11, *map(int, time)) # map them from str to int
        for i in timestamps
        if (time := i.split(':')) # assign the list to the variable time
    ]
    print(timestamps_dt)
    

    But then it will lead to a question why not just,

    timestamps_dt = [
        datetime(2020,11, *map(int, i.split(':'))) 
        for i in timestamps
    ]
    

    Reference PEP-572