I am so excited after learning how to build a list comprehension , I managed to convert 8 lines of code just into 2 lines ,
the first list comprehension gets me the folder and the second gets me the files of specific filter,
hideTheseFolders=[".thumb",".mayaSwatches","RECYCLER","$AVG"]
fileFilters=["ma","jpg","png","mb",'iff','tga','tif']
newLst=[]
import os
locationTxt="E:\box\scripts"
[newLst.append(each) for each in os.listdir(locationTxt) if os.path.isdir(os.path.join(locationTxt,each)) and each not in hideTheseFolders]
[newLst.append(os.path.basename(os.path.join(locationTxt,each))) for nfile in fileFilters for each in os.listdir(locationTxt) if each.endswith(nfile)]
now in the above code the last two lines are looking inside same diretory from locationTxt , which means their is probrbaly a way that i can merge last two lines. can anyone please show me super quick , I am already so excited that i cant wait…:):
List comprehensions are great, but don’t confuse fewer lines of code with more legible code. Sometimes it is better to use more lines of code if it makes it easier for another person to glance at the code and quickly grasp what you are doing. List comprehensions can sometimes be incomprehensible to another person!
What rgkovach said… Between this and lambda, you can create some pretty obfuscated code. So long as you have decent python folks on the project, then it’s probably fine to “go wide” with this kind of stuff, but a 20 year veteran of C++ coding will look at this and scratch his head for a minute.
That said, there are cases where this is the perfect solution.
In your particular example, it looks like you aren’t actually doing anything with the result of the comprehension, you are just using the structure to pack code onto a single line. I wouldn’t try packing code for the sake of packing code. All you’re doing is removing whitespace and line endings.
++ to the advice above - i’t s hard to maintain code if you have to take it apart to remember how it works.
The primary uses for comprehension are:
grabbing the result of an iterator (possibly with a filter) into a permanent list: files = [f for f in list_files() if f.endswth(“mb”)]
converting between iterable types: example = “abcde”; letters = [x for x in example] # this is handy for data packed into strings!
simple list processing : strings = [str(x) for x in list_of_numbers]
more complex list processing with lambdas for readbility:
filter_func = lambda p, q: p > q
larger_than_last = [val for val in list_of_numbers if filter_func(val, 5)]
I’d definitely avoid nesting comprehensions, it makes for very hard to read code. As a rule of thumb, if you can do your processing with one or two tests, you can use a comprehension and maybe some lambdas to clean it up. If you need to do more than two tests, it’s wiser to just use a for-loop… especially if you can imagine that your filtering criteria might evolve over time.
Many of these functions overlap with the builtin functions map and filter, although is considered more ‘stylish’ to use comprehensions.
well enough said for list comprehensions I would stick to full code, I believe you guys interms of readability. but for this I will use two lines and wont dare further nesting. @btribble: the newLst is actually replaced by textScrollList of command module of maya, I was working on the projectfor which I built explorer/ finder like functionality with some extra features, however now that I have blogged and share the code of what I learnt I would guess I don’t have to worry about forgetting , I can easily refer to my blog to see what I did in the past.
Ah I remember when I first learned list comprehensions, trying to stuff them everywhere I could; made for some obnoxious code haha.
Just seconding the above advice, try to avoid using nested comprehensions unless they’re simple and easy to figure out. It ends up being a headache for anyone (including yourself) that comes along and tries to update your code later. I think the only time I end up using them is to flatten nested lists like:
flattened = [item for row in matrix for item in row]
And just a couple of comments on the comprehensions you’re using in that first post:
list comprehensions return a list comprised of the results of each iteration. This makes the append in the comprehension unnecessary, and as btribble said it’s just code-packing. You can just capture the returned value and get the same result. If you want to add the results to an existing list use:
myList.extend([list_comprehension])
otherwise:
myList = [list_comprehension]
Secondly, and unrelated to the comprehension is that calling basename(join(basedir, filename)) on the result of listdir will give you the same result as just using the output of listdir. os.listdir returns the basename of each file/dir in that directory, and calling basename() on a join() just gives you the basename anyway.