Handling Large Lists

Sometimes for-loops on the Python side are too slow, because every iteration sends a SKILL command and waits for the answer to it. In some cases we can “move” the for-loop to the SKILL side.

This naive code example queries all shapes and deletes some of them. The attribute access and the delete function both trigger a SKILL command on each iteration.

cv = ws.ge.get_edit_cell_view()

for shape in cv.shapes:
    if shape.layer == 'M1':
        ws.db.delete_object(shape)

Another problem occurs when only a single item of a long list is needed. The following code example receives the complete list from SKILL twice and then takes a single element/and the length out of it.

cv = ws.ge.get_edit_cell_view()

print(cv.shapes[0])
print(len(cv.shapes))

The class LazyList can help us in these situations. The first step is to use the lazy attribute of the remote object. After that filtering, for-loops and accessing single items becomes very efficient.

cv = ws.ge.get_edit_cell_view()
shapes = cv.lazy.shapes  # notice the `lazy` attribute

print(shapes[0])  # only one item is transferred
print(len(shapes))  # length is calculated in SKILL

shapes.filter(layer='M1').foreach(ws.db.delete_object)  # filtering and deletion is done in SKILL

print(shapes[:])  # in case you still need it: the whole list

Warning

Try to combine multiple filters into a single call to LazyList.filter. Multiple filter calls in Python will result in multiple filter calls in SKILL.

shapes.filter(layer='M1', purpose='...')  # better
shapes.filter(layer='M1').filter(purpose='...')  # worse

Warning

Don’t use C-like for loops with LazyList

for i in range(len(shapes)):
    print(shapes[i])  # very slow

This runs in quadratic time.

Advanced usage of LazyList.foreach

LazyList.foreach has three forms. You can pass a remote function with arguments, without arguments or a lazily evaluated remote function.

The simple form is without arguments. In this case every item of the list is passed as the single argument to the function.

shapes.foreach(ws.db.delete_object)

If you need additional arguments, you can use the following form. In this example the function is called with two arguments. The first is the element of the list and the second is a constant we provided.

shapes.foreach(ws.example.move_object, LazyList.arg, [10, 10])

Alternatively you can use the following syntax which is equivalent to the second form.

shapes.foreach(ws.example.move_object.lazy(LazyList.arg, [10, 10]))  # notice the `lazy` attribute