The [Reading geometries](http://desktop.arcgis.com/en/arcmap/latest/analyze/python/reading-geometries.htm) documentation shows the proper processing procedure for sub-parts in polygons: ```python for row in arcpy.da.SearchCursor(infc, ["OID@", "SHAPE@"]): # Print the current multipoint's ID # print("Feature {}:".format(row[0])) partnum = 0 # Step through each part of the feature # for part in row[1]: # Print the part number # print("Part {}:".format(partnum)) # Step through each vertex in the feature # for pnt in part: if pnt: # Print x,y coordinates of current point # print("{}, {}".format(pnt.X, pnt.Y)) else: # If pnt is None, this represents an interior ring # print("Interior Ring:") partnum += 1 ``` Note the `if pnt` test, with the comment > If pnt is None, this represents an interior ring Some comments: - Your inner loop is so inefficient, I can't copy it in good conscience. This should be a simple matrix or sparse dictionary of arrays, populated once above the top of the code. - It should be a crime (misdemeanor data abuse) to not use the `spatial_reference` parameter in the `arcpy.Polygon` constructor -- failure to do so will truncate your coordinates to the third decimal place. - The `with` construct deletes variables, so your `del` statements were no-op. And the corrected code block: ```python desc = arcpy.Describe(polygon_fc) sr = desc.spatialReference with arcpy.da.UpdateCursor(polygon_fc, my_field) as myUpdtCur: for row in myUpdtCur: geom = row[0] arr_pol = arcpy.Array() for part in geom: arr_part = arcpy.Array() pnt_count = 0 for pnt in part: if not pnt: arr_part.add(None) # Close previous subpart continue # <-- Skips hole markers ## assign updZpnt here pnt_count += 1 print pnt_count myXYZPoint = arcpy.Point(pnt.X, pnt.Y, updZpnt) arr_part.add(myXYZPoint) arr_pol.add(arr_part) row[0] = arcpy.Polygon(arr_pol,sr, True) myUpdtCur.updateRow(row) ```