Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any significance of the triple underscores in this python for loop?

Is there any significance in the triple underscore in Python?

This was in a script for getting all .txt files in a directory.

for ___,___,files in os.walk(some_folder):
    files[:]=[x for x in files if x.lower().endswith('txt')]
    for file in files:

Reading other questions on here a single underscore is normally used for throw away variables, is this use of a triple underscore just bad practice or is there significance to it?

like image 454
Notts90 supports Monica Avatar asked Jan 04 '23 07:01

Notts90 supports Monica


2 Answers

Single, double, triple and, in general, any amount of underscore only names in a script implicitly signifies that the value will not be used (the fact that it isn't given a "name" using any letters signifies this).

This is, of course, not set in stone (that is, Python doesn't treat ___ any differently than a name like foo) instead it's a convention programmers usually understand and respect.

The single underscore has a purpose only in interactive mode and it's the one that's employed in scripts instead of __ or ___. Using ___ and __ just look ugly and really are completely unecessary; I can't see why someone would decide to use it over _; don't copy them and opt for _ when you need to get the same message across.

like image 72
Dimitris Fasarakis Hilliard Avatar answered Jan 06 '23 20:01

Dimitris Fasarakis Hilliard


Like Jim said, the ___ syntax usually means whatever is captured by that name (___) isn't useful, or is garbage. Take a look at the following example, for the sake of completeness:

I have a folder, test, with the following structure:

test
    subtest1
        file1.txt
        file2.txt
    subtest2
        file3.txt

Look what happens when I use os.walk on test:

>>> list(os.walk('test'))
[('test', ['subtest1', 'subtest2'], ['.DS_Store']), ('test/subtest1', [], ['file1.txt', 'file2.txt']), ('test/subtest2', [], ['file3.txt'])]
>>> len(list(os.walk('test')))
3

So there are technically three elements in the generator returned by os.walk('test'). How many elements are within each element, though, since we clearly see some nested data structures?

>>> [len(x) for x in os.walk('test')]
[3, 3, 3]

Okay, there are three subelements in each element of os.walk('test'). For example, at list(os.walk('test'))[0], there is 'test' (the first element), ['subtest1', 'subtest2'] (the second element), and ['.DS_Store'] (the third and final element). The last element contains the non-directory files in whatever folder is denoted by the first element (so .DS_Store is a file in the test directory).

Let's get to your for loop, then (I won't use the underscores yet):

>>> for main_dir, sub_dirs, files in os.walk('test'):
...         print("Main directory: ", main_dir)
...         print("Sub-directories: ", ', '.join(sub_dirs))
...         print("Files: ", ', '.join(files))
... 
Main directory:  test
Sub-directories:  subtest1, subtest2
Files:  .DS_Store
Main directory:  test/subtest1
Sub-directories:  
Files:  file1.txt, file2.txt
Main directory:  test/subtest2
Sub-directories:  
Files:  file3.txt

So the for main_dir, sub_dirs, files in os.walk('test') syntax is really what we call "unpacking." We are assigning to main_dir the first element in os.walk('test'), to sub_dirs the second element, etc. The ___ syntax (which really should be just _), says to the reader, "Forget about these values; I've named the ones I need." In your case, the code is saying, "Forget about the directories from which these files come; I just want the filenames themselves."

like image 29
blacksite Avatar answered Jan 06 '23 22:01

blacksite