-1

Someone has challenged me to create a program that sorts their pictures into folders based on the month they were taken, and I want to do it in one line (I know, it's inefficient and unreadable, but I still want to do it because one-liners are cool)

I needed a for loop to accomplish this, but the only way I know of to use a for loop in one line is list comprehension, so that's what I did, but it creates an empty list, and doesn't print anything from the list or anything.

What I'm doing is renaming the file to be the month created + original filename (ex: bacon.jpg --> May\bacon.jpg)

Here is my code (Python 3.7.3):

import time
import os.path
[os.rename(str(os.fspath(f)), str(time.ctime(os.path.getctime(str(os.fspath(f))))).split()[1] + '\\' + str(os.fspath(f))) for f in os.listdir() if f.endswith('.jpg')]

and the more readable, non-list-comprehension version:

import time
import os.path
for f in os.listdir():
    fn = str(os.fspath(f))
    dateCreated = str(time.ctime(os.path.getctime(fn)))
    monthCreated = dateCreated.split()[1]
    os.rename(fn, monthCreated + '\\' + fn)

Is list comprehension a bad way to do it? Also, is there a reason why, if I print the list it's [] instead of [None, None, None, None, None, (continuing "None"s for every image moved)]?

Please note: I understand that it's inefficient and bad practice. If I were doing this for purposes other than just for fun to see if I could do it, I would obviously not try to do it in one line.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • If it's just printing `[]`, are you sure that the `if f.endswith` is doing what you want? – C.Nivs May 28 '19 at 20:49
  • DO NOT use list comprehension unless you plan to use the result, it is not a way to one line a `for` loop. You should NOT one line this problem. If you want you can use `;` but that is poor practice. – Error - Syntactical Remorse May 28 '19 at 20:50
  • 4
    Trying to shove your whole program into one line is like trying to shove your whole family into one pair of underpants. Maybe you can do it, but please don't. – user2357112 May 28 '19 at 20:51
  • @Error-SyntacticalRemorse It's totally fine for golfing or when otherwise messing around. – ruohola May 28 '19 at 20:52
  • @ruohola than just use `;` to write multiple lines in one. List comprehension consumes memory for each loop, best case it uses `None` for each call, worst case each call returns a large object thus making a large temporary list that is never used. – Error - Syntactical Remorse May 28 '19 at 20:54
  • 1
    The efficiency of list comprehensions is primarily in creating a list, shortcutting the `lst.append(item)` step of a loop. If you're not trying to create a list, then a list comp is nonsensical. Because you're adding the return of a function to a list, and the function returns `None`, you get a list of `None` – G. Anderson May 28 '19 at 21:05
  • @C.Nivs it is moving the pictures to the appropriate folder, so I assume that its working correctly. – rainbowkitty227 May 28 '19 at 22:01
  • @user2357112 lol, nice metaphor. I agree with you, and I have now realized that I require my program to be more complicated, so I'm expanding it to multiple lines – rainbowkitty227 May 28 '19 at 22:03

2 Answers2

1

This is bad in two immediate respects:

  1. You're using a list comprehension when you're not actually interested in constructing a list -- you ignore the object you just constructed.
  2. Your construction has an ugly side effect in the OS.

Your purpose appears to be renaming a sequence of files, not constructing a list. The Python facility you want is, I believe, the map function. Write a function to change one file name, and then use map on a list of file names -- or tuples of old, new file names -- to run through the sequence of desired changes.

Prune
  • 76,765
  • 14
  • 60
  • 81
0

Is list comprehension a bad way to do it?

YES. But if you want to do it in one line, it is either that or using ";". For instance:

 for x in range(5): print(x);print(x+2)

And, by the way, just renaming a file including a slash will not create a folder. You have to use os.mkdir('foldername').

In the end, if you really want to do that, I would just recommend doing it normally in many lines and then separating it with semicolons in a single line.

Homero Esmeraldo
  • 1,864
  • 2
  • 18
  • 34