Getting a list of data from object properties using list comprehension

Most objects in Blender have multiple lists of data in their structure. For example, inside a “mesh” object there are list with vertices of this mesh, the list of mesh edges, and the list of mesh polygons. And in the structure of each mesh vertex there is, for example, a list with its coordinates along the X, Y and Z axes.

To access such internal data lists, we usually have to create loops of several levels of nesting. However, in the Python language, which is used in the Blender API, there is a convenient ability to form such nested loops in a single line – list comprehension.

Let’s consider a simple example: we have several selected polygons on the mesh, and we need to find the maximum coordinate along the Z axis among the vertices of these polygons.

In common way, we will first create a loop through the selected polygons:

Create another loop based on the vertexes belonging to the selected polygons inside it:

And only inside it, we will be able to access the coordinates of each vertex. This results in the following code structure consisting of four levels of nesting:

But using the list comprehension, we can write this entire expression in a single line.

This is how list comprehension in Python works: one level of loop that produces a list is written to a string in square brackets. On the left is the resulting expression for each iteration of the loop, on the right, if necessary, an additional condition.

new_list = [expression for item in iterable (if condition)]

So the first and second levels of our code can be represented by the following one-line expression:

Having expanded only the first two levels into a string using list comprehension, we get a list of lists – each element of the new list is itself a list with vertex coordinates.

We could loop through the resulting list again:

The level of nesting has become slightly smaller, but there is still chance for further compression, since list comprehension in Python supports several levels of nesting.

Each subsequent level is written from left to right, with an optional conditions. The expression on the left can operate on variables from the last (most often), or from each of the levels.

Let’s continue turning our code into a one-liner.

On the left, we specify the final expression to obtain the Z coordinate of the vertex. Next, from left to right, we write expressions from each level of code and conditions, if exists.

We will get the following line of code:

As a result, we received exactly the same list of values as when using multi-level loops.

Let’s look at another example: we have several selected vertices on a mesh, and we need to get a list of edges coming out of these vertices that are not selected.

To get edges associated with vertices, we can use the bmesh object.

First, let’s get a list of unselected edges in the usual way, using nested loops:

And next, get this list using list comprehension, writing all the code in one line.

Specify the final expression – what exactly we get in the list, on the left. In our case, this is edge. Next, from left to right, we write each level with optionally a condition.

We received the same list of edges we needed, using only one line of code.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comment
Inline Feedbacks
View all comments