Of course! Here is a comprehensive guide to indexing in Maya Python, covering everything from basic Python lists to Maya-specific API (C++) object indexing.

The Basics: Python List and Tuple Indexing
This is the foundation. In Maya, almost every collection of objects (like a list of selected objects, a list of vertices in a mesh, etc.) is a Python list or tuple. Python lists are zero-indexed, meaning the first element is at index 0.
Positive Indexing (from the start)
Indexing starts at 0 and increments.
# Let's get a list of selected objects
selection = cmds.ls(selection=True)
# Check if we have a selection
if not selection:
cmds.warning("Nothing is selected!")
# Let's say the user selected ['pCube1', 'pSphere1', 'pCone1']
# selection[0] -> 'pCube1'
# selection[1] -> 'pSphere1'
# selection[2] -> 'pCone1'
# Get the first selected object
first_obj = selection[0]
print(f"First object: {first_obj}")
# Get the third selected object
third_obj = selection[2]
print(f"Third object: {third_obj}")
Negative Indexing (from the end)
Negative indexing starts at -1 for the last element.
# Using the same selection: ['pCube1', 'pSphere1', 'pCone1']
# selection[-1] -> 'pCone1' (last element)
# selection[-2] -> 'pSphere1' (second to last)
# selection[-3] -> 'pCube1' (third to last)
# Get the last selected object
last_obj = selection[-1]
print(f"Last object: {last_obj}")
Slicing (getting a range of elements)
Slicing allows you to get a subset of a list. The syntax is [start:stop:step].
start: The index to start at (inclusive).stop: The index to end at (exclusive).step: The interval between elements.
# selection = ['pCube1', 'pSphere1', 'pCone1', 'pTorus1', 'pPlane1']
# Get the first two elements (indices 0 and 1)
first_two = selection[0:2]
print(f"First two: {first_two}") # Output: ['pCube1', 'pSphere1']
# Get from the second element to the end
from_second_on = selection[1:]
print(f"From second on: {from_second_on}") # Output: ['pSphere1', 'pCone1', 'pTorus1', 'pPlane1']
# Get the last two elements
last_two = selection[-2:]
print(f"Last two: {last_two}") # Output: ['pTorus1', 'pPlane1']
# Get every other element
every_other = selection[::2]
print(f"Every other: {every_other}") # Output: ['pCube1', 'pCone1', 'pPlane1']
Indexing Components (Vertices, Edges, Faces)
This is a very common task in Maya scripting. You use component selection syntax: object.componentType[index].
The component types are:
.vtxor.vertexfor vertices.eor.edgefor edges.for.facefor polygons.cvfor NURBS control vertices
Example: Selecting Specific Vertices
import maya.cmds as cmds
# Create a simple polygon cube
cube = cmds.polyCube(name='myCube')[0]
# Select the first vertex (index 0)
cmds.select(f'{cube}.vtx[0]')
# Select vertices at index 0, 2, and 4
cmds.select(f'{cube}.vtx[0, 2, 4]')
# Select a range of vertices from index 1 to 5 (inclusive)
# Note: The stop index is inclusive for component selection, unlike Python slicing.
cmds.select(f'{cube}.vtx[1:5]')
# Select the last vertex
cmds.select(f'{cube}.vtx[-1]')
# Select the first 3 vertices
cmds.select(f'{cube}.vtx[:3]')
# Clear selection
cmds.select(clear=True)
Getting Component Information
You can use cmds.ls with the long=True flag to get the full names of selected components.
# Select a few vertices manually in the viewport or with code:
cmds.select(f'{cube}.vtx[0, 3, 5]')
# Get the long names of the selected components
selected_components = cmds.ls(selection=True, long=True)
print(selected_components)
# Output might look like:
# [u'|myCube|myShape.vtx[0]', u'|myCube|myShape.vtx[3]', u'|myCube|myShape.vtx[5]']
# You can parse this to get the index
for comp in selected_components:
# Split the string to get the index part
index_part = comp.split('vtx[')[1].split(']')[0]
print(f"Component index: {index_part}")
Indexing Maya API Objects (MIt*, MSelectionList, MDagPath)
When you need high performance or access to lower-level data, you use the Maya Python API (maya.OpenMaya). Indexing here is different and more powerful.
MSelectionList
This is a container for selection items. It's like a list of selections, but for API objects.
import maya.OpenMaya as om
# Create an MSelectionList
sel_list = om.MSelectionList()
# Add an object to the list by name
sel_list.add("pCube1")
# Check if the list has an item at a specific index
if sel_list.length() > 0:
# Get the MObject at index 0
mobject = om.MObject()
sel_list.getDependNode(0, mobject) # Get the node at index 0
print(f"Got MObject for pCube1 at index 0")
MItDependencyGraph (MDagPath)
This iterator is used to traverse nodes in the dependency graph. It's fundamental for finding connected nodes.
import maya.OpenMaya as om
# Get the selection as an MSelectionList
selection = om.MSelectionList()
om.MGlobal.getActiveSelectionList(selection)
if selection.length() > 0:
# Get the first selected item as an MDagPath
dag_path = om.MDagPath()
selection.getDagPath(0, dag_path) # Get the DAG path at index 0
print(f"Selected DAG Path: {dag_path.fullPathName()}")
# You can also get the MObject
mobject = om.MObject()
selection.getDependNode(0, mobject)
print(f"Selected MObject: {mobject.apiTypeStr()}")
MItGeometry (for Mesh Components)
This is the most efficient way to iterate over all vertices, edges, or faces of a mesh.
import maya.OpenMaya as om
# Get the selection
selection = om.MSelectionList()
om.MGlobal.getActiveSelectionList(selection)
if selection.length() > 0:
# Get the DAG path of the selected mesh
dag_path = om.MDagPath()
selection.getDagPath(0, dag_path)
# Create the MItGeometry iterator
geo_iter = om.MItGeometry(dag_path)
# Get the number of components (vertices)
num_vertices = geo_iter.count()
print(f"Mesh has {num_vertices} vertices.")
# Loop through all vertices using the iterator
# The iterator manages the index for you
while not geo_iter.isDone():
# Get the current point (vertex position) in world space
point = om.MPoint()
geo_iter.getPosition(point)
# Get the current index
index = geo_iter.index()
print(f"Vertex {index}: X={point.x}, Y={point.y}, Z={point.z}")
# Go to the next component
geo_iter.next()
Indexing in cmds.list* Commands
Many cmds.list commands return lists. You can index them directly.
import maya.cmds as cmds
# Create some joints
cmds.joint(name='joint1')
cmds.joint(name='joint2')
cmds.joint(name='joint3')
# Get all joints in the scene
all_joints = cmds.ls(type='joint')
print(f"All joints: {all_joints}")
# Output: ['joint1', 'joint2', 'joint3']
# Get the first joint created
first_joint = all_joints[0]
print(f"First joint: {first_joint}")
# Get the children of the first joint
children = cmds.listRelatives(first_joint, children=True)
if children:
print(f"Children of {first_joint}: {children}")
# Get the first child
first_child = children[0]
print(f"First child: {first_child}")
Summary and Best Practices
| Context | Indexing Method | Example | Notes |
|---|---|---|---|
| General Python | Standard list/tuple indexing | selection[0], selection[-1] |
Use for lists of object names, strings, etc. |
| Component Selection | String-based indexing | cube.vtx[0:5] |
Used with cmds.select(). Stop index is inclusive. |
| Maya API (High Perf.) | API Iterators (MIt...) |
geo_iter.index() |
Best for performance. The iterator manages the index. Use MSelectionList.get...() to get items by index. |
| Maya API (Data Access) | API Object Containers | sel_list.getDagPath(0, dag_path) |
Use MSelectionList to hold and retrieve API objects by index. |
Key Takeaway:
- For simple scripting and UI, use Python list indexing on the results of
cmds.ls()and other list-returning commands. - For component selection in the viewport, use the string-based indexing (
object.vtx[index]). - For performance-critical tasks (like iterating over thousands of vertices), use the Maya Python API (
maya.OpenMaya) and its iterators (MItGeometry,MItDependencyGraph). They are significantly faster than looping withcmds.polyInfo()orcmds.polyListComponentConversion.
