Reputation: 21
I'm writing a function that recursively traverses the file system, and returns a list of all files with the .txt
extension.
The pass_test_func
parameter is just a function that can be run and checked (i.e. is the file greater than 100 bytes, etc) - The nothing
function (set as its default), simply returns its argument.
My implementation:
def visit(dname, pass_test_func=nothing):
directory = os.listdir(dname)
byte_list = []
for file in directory:
file_dir = os.path.join(dname, file)
if os.path.isfile(file_dir) and file_dir.lower().endswith('.txt'):
size = os.path.getsize(file_dir)
if pass_test_func(size):
byte_list.append(str(size) + ' ' + file_dir)
elif os.path.isdir(file_dir):
visit(file_dir, pass_test_func)
return byte_list
My problem is that when I recursively call visit
in the following lines
elif os.path.isdir(file_dir):
visit(file_dir, pass_test_func)
the byte_list
is cleared to empty again. I understand why this is happening, but have no idea how I would fix it. The list has to be defined within the definition of visit
, so whenever I use recursion it will always be reset no matter what right? Maybe some other data structure is better suited, like a tuple or dictionary?
Upvotes: 1
Views: 194
Reputation: 103447
Your function returns byte_list
, so just append the returned value when you make your recursive call, instead of throwing it away as you currently do:
elif os.path.isdir(file_dir):
byte_list += visit(file_dir, pass_test_func)
Upvotes: 3
Reputation: 155363
Add an optional argument that can be used in the recursive case:
# Using * makes byte_list keyword-only, so it can't be passed by normal callers by accident
def visit(dname, pass_test_func=nothing, *, byte_list=None):
directory = os.listdir(dname)
# When not passed explicitly, initialize as empty list
if byte_list is None:
byte_list = []
for file in directory:
file_dir = os.path.join(dname, file)
if os.path.isfile(file_dir) and file_dir.lower().endswith('.txt'):
size = os.path.getsize(file_dir)
if pass_test_func(size):
byte_list.append(str(size) + ' ' + file_dir)
elif os.path.isdir(file_dir):
# Pass explicitly to recursive call
visit(file_dir, pass_test_func, byte_list=byte_list)
return byte_list
As an alternative, as suggested by Blorgbeard, since you return byte_list
, use that for your visit
calls, changing only a single line in your original code:
visit(file_dir, pass_test_func)
to:
byte_list += visit(file_dir, pass_test_func)
This creates additional temporary list
s, but that's usually not a big deal.
Upvotes: 2