Select to view content in your preferred language

List Comprehensions

2499
3
01-13-2010 08:26 AM
TedCronin
MVP Honored Contributor
To Jason --


So, awhile back when I spoke to you on the phone about ListLayers and how they were objects rather than strings, you mentioned that I could use a List Comprehension to achieve my results.  I am wondering if you could post some sample code of how to use list comprehensions with arcpy.  Even perhaps as a blog post.
0 Kudos
3 Replies
JasonScheirer
Regular Contributor II
I'm working on a longer-form version of this for a blog post, but here's the gist:

The Map Document object lives in the arcpy.mapping module. To create a new Map Document object is easy, simply call arcpy.mapping.MapDocument with the path to the MXD you wish to use:

mxd = arcpy.mapping.MapDocument('d:\\path\\to\\map.mxd')

Something to note about python strings: backslashes need to be either escaped like 'd:\\path\\to\\map.mxd' or the string can be flagged as a raw string with the r flag like r'd:\\path\\to\\map.mxd'.

In these examples Iâ??ll be using the Python window in ArcGIS Desktop. The Map document object also accepts the special path string â??currentâ?? in desktop only that lets you manipulate the current document in the window:

mxd = arcpy.mapping.MapDocument('current')

From here the interactive window is a great resource to learn and experiment. I can get an idea of what type of properties a map document has by typing in the name of my variable, hitting dot, and see what I have access to.

This makes prototyping and exploring Python code easy, because of the immediate nature of the feedback given in the interactive window. I get a result as soon second I press enter, without needing to save or compile any code.

Layers can be accessed from .lyr files or from the TOC in a Map document. To load from a layer file:

lyr = arcpy.mapping.MapDocument('d:\\path\\to\\layer.lyr')

Layers can be retrieved from a map document by using the arcpy.mapping.ListLayers function as well. In my interatice session I have a simple MXD with some OpenStreetMap data in it, and from the Python window
I issue the ListLayers function and get:

>>> arcpy.mapping.ListLayers(mxd)
[<map group layer u'OpenStreetMap data'>, <map layer u'california_poi'>, <map layer u'california_highway'>, <map layer u'california_natural'>, <map layer u'states'>]

Note this is different than the list of strings in functions such as ListDatasets, it is actual layer objects. If I just want a list of the names from these objects, I can employ a list comprehension:

>>> [lyr.longName for lyr in arcpy.mapping.ListLayers(mxd)]
[u'OpenStreetMap data', u'OpenStreetMap data\\california_poi', u'OpenStreetMap data\\california_highway', u'OpenStreetMap data\\california_natural', u'states']

List comprehensions are a shortcut built into Python for a common type of for loop where one loops over a list of values to produce a new list of values. In this case, weâ??re grabbing the longName attribute from each value in the list returned from ListLayers. The general formula for a list comprehension is:
Simple: [expression for value in list]
With conditional: [expression for value in list if condition]

The if condition form allows one to not only map values, but also apply a conditional filter and only include certain values in the new list. For examples, I only want all the layer names that are feature layers:

>>> [lyr.longName for lyr in arcpy.mapping.ListLayers(mxd) if lyr.isFeatureLayer]
[u'OpenStreetMap data\\california_poi', u'OpenStreetMap data\\california_highway', u'OpenStreetMap data\\california_natural', u'states']


Note the group layer named OpenStreetMap data is no longer included in the results. This also makes it possible to fetch a layer by a specific name and only work with it:

>>> lyrlist = [lyr for lyr in arcpy.mapping.ListLayers(mxd) if lyr.name == "california_highway"]
>>> lyrlist
[<map layer u'california_highway'>]
>>> if lyrlist:
... lyr = lyrlist.pop() # pop takes one element out of end of the list and returns it
...
>>> lyr
<map layer u'california_highway'>
>>> lyr.name
u'california_highway'
>>> lyr.dataSource
u'C:\\DATA\\openstreetmap.gdb\\california_highway'
>>> lyr.transparency
0
>>> lyr.transparency = 10

Many common scenarios for finding and manipulating layers can be accomplished using the built-in functions in arcpy.mapping and a little bit of manipulation with a list comprehension.
0 Kudos
TedCronin
MVP Honored Contributor
Thank you Jason.
0 Kudos
TedCronin
MVP Honored Contributor
I'm working on a longer-form version of this for a blog post, but here's the gist: 

The Map Document object lives in the arcpy.mapping module. To create a new Map Document object is easy, simply call arcpy.mapping.MapDocument with the path to the MXD you wish to use: 

mxd = arcpy.mapping.MapDocument('d:\\path\\to\\map.mxd')

Something to note about python strings: backslashes need to be either escaped like   'd:\\path\\to\\map.mxd' or the string can be flagged as a raw string with the r flag like   r'd:\\path\\to\\map.mxd'

In these examples Iâ??ll be using the Python window in ArcGIS Desktop. The Map document object also accepts the special path string â??currentâ?? in desktop only that lets you manipulate the current document in the window: 

mxd = arcpy.mapping.MapDocument('current')

From here the interactive window is a great resource to learn and experiment. I can get an idea of what type of properties a map document has by typing in the name of my variable, hitting dot, and see what I have access to. 
  
This makes prototyping and exploring Python code easy, because of the immediate nature of the feedback given in the interactive window. I get a result as soon second I press enter, without needing to save or compile any code. 

Layers can be accessed from .lyr files or from the TOC in a Map document. To load from a layer file: 

lyr = arcpy.mapping.MapDocument('d:\\path\\to\\layer.lyr')

Layers can be retrieved from a map document by using the arcpy.mapping.ListLayers function as well. In my interatice session I have a simple MXD with some OpenStreetMap data in it, and from the Python window 
I issue the ListLayers function and get: 

>>> arcpy.mapping.ListLayers(mxd)
[<map group layer u'OpenStreetMap data'>, <map layer u'california_poi'>, <map layer u'california_highway'>, <map layer u'california_natural'>, <map layer u'states'>]


Note this is different than the list of strings in functions such as ListDatasets, it is actual layer objects. If I just want a list of the names from these objects, I can employ a list comprehension: 

>>> [lyr.longName for lyr in arcpy.mapping.ListLayers(mxd)]
[u'OpenStreetMap data', u'OpenStreetMap data\\california_poi', u'OpenStreetMap data\\california_highway', u'OpenStreetMap data\\california_natural', u'states']


List comprehensions are a shortcut built into Python for a common type of for loop where one loops over a list of values to produce a new list of values. In this case, weâ??re grabbing the longName attribute from each value in the list returned from ListLayers. The general formula for a list comprehension is: 
Simple:   [expression for value in list]
With conditional:   [expression for value in list if condition]

The   if condition form allows one to not only map values, but also apply a conditional filter and only include certain values in the new list. For examples, I only want all the layer names that are feature layers: 

>>> [lyr.longName for lyr in arcpy.mapping.ListLayers(mxd) if lyr.isFeatureLayer]
[u'OpenStreetMap data\\california_poi', u'OpenStreetMap data\\california_highway', u'OpenStreetMap data\\california_natural', u'states']


Note the group layer named OpenStreetMap data is no longer included in the results. This also makes it possible to fetch a layer by a specific name and only work with it: 

>>> lyrlist = [lyr for lyr in arcpy.mapping.ListLayers(mxd) if lyr.name == "california_highway"]
>>> lyrlist
[<map layer u'california_highway'>]
>>> if lyrlist:
... lyr = lyrlist.pop() # pop takes one element out of end of the list and returns it
...
>>> lyr
<map layer u'california_highway'>
>>> lyr.name
u'california_highway'
>>> lyr.dataSource
u'C:\\DATA\\openstreetmap.gdb\\california_highway'
>>> lyr.transparency
0
>>> lyr.transparency = 10


Many common scenarios for finding and manipulating layers can be accomplished using the built-in functions in arcpy.mapping and a little bit of manipulation with a list comprehension.


By chance has there been a blog entry going over this a bit more?
0 Kudos