0

I have a list of dict objects of type Case which are initiated with a dict. When running in Python2, I could loop over keys and values, to facilitate both Python versions I'm using the six library.

class Case:

    def __init__(self, obj):

        properties = {}
        # standardize Boolean properties
        true_values = ['1', 1, True, 'yes', 'Yes', 'YES']
        false_values = ['0', 0, False, 'no', 'No', 'NO']
        for (k, v) in iteritems(properties):
            # standardize TRUE values
            if v in true_values:
                properties[k] = True
            # standardize FALSE values
            elif v in false_values:
                properties[k] = False
            # keep String values
            elif isinstance(v, str):
                continue

        # remove NULL values
        filtered = {k: v for (k, v) in iteritems(properties) if v != None}

        # set Case instance attribute for each property
        for (k, v) in iteritems(filtered):
            setattr(self, k, v)

    def __iter__(self):
        return self

    def __getitem__(self, key):
        return self.__dict__.get(key, None)

    def to_json(self):
        return json.dumps(self, default=lambda o: o.__dict__)

When I loop over this list, I get an AttributeError despite following six documentation.

I iterate through a list of above objects:

from six import iteritems

def transform(case_list):
    for case in case_list:
        for (key, value) in iteritems(case): #crashes here
            #do stuff

But get an AttributeError every time:

Traceback (most recent call last):
File "app/run.py", line 134, in <module>
main()
File "/home/user/other.py", line 55, in transform
for (key, value) in iteritems(case):
File "/home/user/env/lib/python3.4/site-packages/six-1.10.0-py3.4.egg/six.py", line 581, in iteritems
return iter(d.items(**kw))
AttributeError: 'Case' object has no attribute 'items'

I call it with python3 app/run.py. Why does it not recognize the iterable?

dh762
  • 2,259
  • 4
  • 25
  • 44
  • 2
    Your error message is coming from some completely different code you haven't shown us, where you're trying to apply `iteritems` to a `Case` object. – user2357112 Dec 01 '16 at 19:28
  • Line 55 is in method `transform`. The other method just calls `transform` with parameter is a list of `Case`s? Sorry I don't get your hint, can you elaborate? – dh762 Dec 01 '16 at 19:32
  • 1
    `six.iteritems()` is meant for objects that have an `.items()` method (ie dictionaries) and your Case object does not have such a method. Implement that method and it will work. – sethmlarson Dec 01 '16 at 19:37
  • 1
    Oh, wait, you did post `transform`. You say "dict objects of type Case", but `Case` objects are not any sort of dict. They don't support the operations required by `six.iteritems`. – user2357112 Dec 01 '16 at 19:38
  • @SethMichaelLarson : thanks I found a solution, see below. – dh762 Dec 01 '16 at 19:47

1 Answers1

0

I found a solution by adding a items() method to Case class:

    def items(self):
        return zip(self.__dict__.values(), self.__dict__.keys())
dh762
  • 2,259
  • 4
  • 25
  • 44
  • 1
    This is the exact opposite of what you want and also gives random ordering of keys and values. Instead you should rely on `self.__dict__.items()` – sethmlarson Dec 01 '16 at 19:55