One of the main reasons I like Python as a scripting language is its brevity – in particular I enjoy using things like list comprehensions, which enable you to escape the use of for loops when dealing with lists. Lists in Python are powerful and when used in combination with map and filter, allow you to do a lot more with a lot less code. This is one of the things I really miss when I write code in VBA/VBScript, where you’re often stuck dealing with either arrays or collections from the object model. Dive Into Python offers an interesting perspective on this.
Dick Kusleika posted a VBA sub to open the newest file in a folder over at Daily Dose of Excel today, which made use of the Scripting library to iterate over .csv files in a folder, find the newest and open it. Dick mentioned wanting an easier way to find the newest than looping over all of them, which got me thinking. If the Scripting.Folder object had a .NewestFile property, then that would obviously do it, but failing that, I could not see any other way than to loop through all files to examine the create dates.
In Python, however, without looping, the exercise becomes a two-line function:
import os, os.path, sys def newest(ext, path=os.getcwd()): """ pre: path a valid absolute filepath or None, ext a file extension (e.g. '.py') returns: newest (last modified on *nix system, last created on Windows) file from path """ file_dict = dict([(fname, \ os.path.getctime(os.path.join(path, fname))) \ for fname in os.listdir(path) \ if os.path.splitext(fname) == ext]) return max(file_dict, key=lambda x: file_dict[x])
I’m not sure at all whether there would be any performance benefit from doing it this way as opposed to looping over the files, but the real benefit of this is that it frees you from the worry of how to construct a for loop over the list of filenames returned from os.listdir(). All you need to worry about is which one of them you want.