JBigos-esristaff

Building a dynamic print statement with cursors

Blog Post created by JBigos-esristaff Employee on Dec 19, 2016

If you have worked with the Data Access Cursors before you have probably written this code 

 

import arcpy
fc = r"D:\EsriTraining\PYTH\Cursors\SanDiego.gdb\MajorAttractions"

flds = ["NAME","ADDR","ESTAB","ZIP"]

with arcpy.da.SearchCursor(fc,flds) as scur:
    for row in scur:
        print " Name: " + row[0] + " Address: " + row[1]

 

A lot

 

Recently I have taken a closer look into how a print statement could be reduced or make it a more dynamic statement.

Having worked with cursors for awhile, you get used to writing print statements in a simple manner maybe starting with concatenation of values:

print " Name: " + row[0] + ", Address: " + row[1]

 

Concatenation works, but managing the different times that you open and close parenthesis can get cumbersome. So you look around a bit and then you see a sample that shows you how to utilize python string formatting:

print " Name: {0} , Address: {1}".format(row[0], row[1])

The code above is great because there is only one set of quotes ( " ) to manage. Open it and close it. What sits inside is what gets printed except for the place holders { }. The numbers inside are a reference to index numbers to the format parameters:

 

.format( 0 , 1)

What I like about the format is not needing to convert values into string. Numbers get converted in a more direct manner and not having to manage multiple quotes ( " ) is a definite plus.

Writing with a lot of these makes you think: 

 

Do I have to hardcode the {1}?

What if I wanted a format that flexes with the length of fields for a simple print statement?

 

A little bit of research gets me 85% of the way there, I just need to modify to fit my needs.

print ' : '.join('{} for {}'.format(i, c) for i, c in enumerate(candidates, 1))

The stackoverflow code uses the enumerate built-in which gives access to the index number of the item, plus the current item. Close but not what I am looking for.

Enter the zip function. The zip function returns a list of tuples where the values from both lists are essentially combined together as a tuple in the the same index.

 

What was that?

 

Let's look the flds variable and what it is:

flds = ["NAME","ADDR","ESTAB","ZIP"]

This is a python list that has 4 values in it, so it's length is 4:

len(flds)

 

The key to getting the stackoverflow code to fit our problem is knowing that the length of the flds equates to the length of the tuple of values or the row variable:

len(row)

Because these 2 lists have the same lengths you can be assured that when you use the zip built-in. The returned tuple will be the right sequence:

zp = zip(flds,row)
print zp

Result:

 

[('NAME', u'PETCO PARK'), ('ESTAB', 2004), ('ADDR', u'100 PARK BLVD'), ('ZIP', u'92101')]

 

Put it all together and this is what the new dynamic flexing print statement looks like:

 

import arcpy
fc = r"D:\EsriTraining\PYTH\Cursors\SanDiego.gdb\MajorAttractions"

flds = ["NAME","ESTAB","ADDR","ZIP"]

with arcpy.da.SearchCursor(fc,flds) as scur:
    for row in scur:
       
        print " : ".join('Field:{} Value:{}'.format(fldName,val) for fldName, val in zip(flds,row))

Hope this helps with writing more dynamic python code!

Outcomes