lambda and map in Maya
Starting using a couple shorthand techniques today via map and lambda to save on screen real estate when authoring Python modules in Maya. I often times will troll the scene for info and want to print stuff:
Here, I find the transform name for all mesh in the scene, then print them all with tabs in front:
import sys import maya.cmds as mc # Get transform for each mesh: shapes = mc.ls(type='mesh') transforms = map(lambda x: mc.listRelatives(x, parent=True)[0], shapes) # print with tab in front: map(lambda x: sys.stdout.write('\t%s\n'%x), transforms)
By using our map / lambda combo, I’m able to side-step the need to write any loops. Here’s how it would look otherwise:
import maya.cmds as mc # Get transform for each mesh: shapes = mc.ls(type='mesh') transforms = [] for s in shapes: transforms.append(mc.listRelatives(s, parent=True)[0]) # print with tab in front: for tran in transforms: print '\t', tran
Not counting imports and comments, I halved the number of lines of code. One could argue the bottom example is possibly more readable however.
Even better than lambda/map is list comprehension (at least for me). The format is:
[ for in if ]
Thusly the above example would be replace:
transforms = map(lambda x: mc.listRelatives(x, parent=True)[0], shapes)
with
transforms = [ mc.listRelatives(x, parent=True)[0] for x in shapes ]
An example of using an option condition is might be to only get meshes suffixed with “Ctrl”
transforms = [ mc.listRelatives(x, parent=True)[0] for x in shapes if mc.listRelatives(x, parent=True)[0].endswith(“Ctrl”) ]
I like how it’s basically the same loop syntax and readability in one line. While you could do that for the last line (or include tabs in first loop), the trick I like to use instead is:
“\n\t”.join(transforms)
Which is essentially the reverse of .split. It takes a list and joins all the items with the given string. You’ll need to indent the print since the first item won’t have the tab but this is a nice way to print lists quickly since it’s only one print instead of several.
Blarg! Because some of code my previous comment were interpreted as html tags, the format for list comprehension is:
[ (result) for (iter variable) in (something iterable) if (optional condition) ]
I agree comprehensions are great And you’re right: Using a list comprehension actually does give you a more control over querying the shapes using the condition. I wonder which is faster though? 😉 Thanks for the tip.