Rewrite Dict Comprehension
Lesson: Rewrite dict comprehension
Rewrite the dict comprehension
dct = {
entry:
'link' if os.path.islink(entry) else
'dir' if os.path.isdir(entry) else
'file' if os.path.isfile(entry) else
'other'
for entry in os.listdir()
}
using a "traditional" for loop and if-else statements.
Remember that a dictionary entry can be set with a dct[key] = value
assignment.
Use help(os.listdir)
for more information about this standard library
function.
This site's repo contains a test directory with some typical (unix)
file types (symbolic link, directory, file) in the
/docs/training/lessons/rewrite-dict-comprehension/test_dir
folder.
Some notes:
- isfile() and isdir() follow symbolic links, so they will return their link target file type. Thus, the islink() condition must come first to actually detect a link file type.
- Windows: no symlinks, a checked-out link from the test_dir is represented as a file and thus recognized as 'file'
Really take a peek now?
rewrite_dict_comprehension.py
import os
import pprint
# Notes:
# - isfile() and isdir() follow symbolic links, so they will return their link
# target file type. Thus, the islink() condition must come first to actually
# detect a link file type.
# - Windows: no symlinks, a checked-out link from the test_dir is represented
# as a file and thus recognized as 'file'
def dict_comp_filetypes_cwd():
"""Return a {<path entry>: <file type} dictionary of the current working
directory.
Uses a dict comprehension.
"""
dct = {
entry:
'link' if os.path.islink(entry) else
'dir' if os.path.isdir(entry) else
'file' if os.path.isfile(entry) else
'other'
for entry in os.listdir()
}
return dct
def dict_comp_filetypes(path='.'):
"""Return a {<path entry>: <file type} dictionary of the given path.
Uses a dict comprehension.
"""
# To avoid joining path + entry to the full path both for the dict key and
# in the value's if-else expression, we (ab)use the walrus operator.
# This *must* sit in the if condition part of the dict comprehension.
#
# Feels a tiny bit hacky, without walrus it looks like this:
#
# dct = {
# os.path.join(path, entry):
# 'link' if os.path.islink(os.path.join(path, entry)) else
# 'dir' if os.path.isdir(os.path.join(path, entry)) else
# 'file' if os.path.isfile(os.path.join(path, entry)) else
# 'other'
# for entry in os.listdir(path)
# }
dct = {
file_path:
'link' if os.path.islink(file_path) else
'dir' if os.path.isdir(file_path) else
'file' if os.path.isfile(file_path) else
'other'
for entry in os.listdir(path)
if (file_path := os.path.join(path, entry))
}
return dct
def for_loop_filetypes(path='.'):
"""Return a {<path entry>: <file type} dictionary of the given path.
Uses a traditional for loop.
"""
dct = {}
for entry in os.listdir(path):
file_path = os.path.join(path, entry)
if os.path.islink(file_path):
file_type = 'link'
elif os.path.isdir(file_path):
file_type = 'dir'
elif os.path.isfile(file_path):
file_type = 'file'
else:
file_typ = 'other'
dct[file_path] = file_type
return dct
def main(path):
func = dict_comp_filetypes_cwd
print(f'\n*** dict comprehension using {func.__name__}')
dct = func()
pprint.pprint(dct)
func = dict_comp_filetypes
print(f'\n*** dict comprehension using {func.__name__}(path={path})')
dct = func(path)
pprint.pprint(dct)
func = for_loop_filetypes
print(f'\n*** dict comprehension using {func.__name__}(path={path})')
dct = func(path)
pprint.pprint(dct)
if __name__ == '__main__':
main(path='./test_dir')