Since I'm most familiar with 10.1+, and cursors in general are a lot better in the `da` module, here's a potential solution. Currently, you are creating a cursor each time you change fields, which means you are taking a hit there. Furthermore, you are checking the field type for each record instead of just using the field type once to filter initially. I've changed how `Null` values are checked, but I haven't thoroughly tested it to check for all possible values. For the small sample dataset I had, it worked @ 10.2.2. #Return None if the value needs to be changed, else return the value def nullify(value): x = value if value is not None: #True null fields are read as None types if type(value) == str: if value.lstrip(' ') == '' or value.lower() == '<null>': x = None else: if value == 0: x = None return x ---------- #We're only interested in some fields ftypes = ("String", "SmallInteger", "Integer", "Double") fieldList = [f.name for f in arcpy.ListFields(fc) if f.type in ftypes] with arcpy.da.UpdateCursor(fc, fieldList) as rows: for row in rows: vals = [r for r in row] nulled = map(nullify, vals) if vals != nulled: #Only update if the row actually needs to be changed. rows.updateRow(nulled)