This is driving me insane. Below is a class I was messing around with, the goal was to have a way to support dynamic attribute assignment. Please forget for a moment the poor implementation or why I didn't just use a dictionary, I know there are other ways to do this (such as Enum) but this was my test code before and now it became my quest to find out why it's not working.
class Family(object):
def children(self):
return self.__dict__.values()
def __setitem__(self, key, value):
self.__dict__[key] = value
def __getitem__(self, item):
return self.__dict__[item]
def __repr__(self):
return str(self.__dict__)
def __iter__(self):
return self.__dict__.items()
This all seems fine, and I initiated a test object as follows:
foo = Family()
foo.a = 'foo'
foo.b = 'bar'
[i for i in foo]
Now the expected outcome was [('a', 'foo'), ('b', 'bar')], but what I got was this instead:
TypeError: iter() returned non-iterator of type 'dict_items'
I thought I might have messed up the __iter__ method, so I checked as follow:
type(foo.__iter__())
# <class 'dict_items'>
type(foo.__dict__.items())
# <class 'dict_items'>
[i for i in foo.__dict.__items()]
# [('a', 'foo'), ('b', 'bar')]
foo.__dict__.items() == foo.__iter__()
# True
If they're both identical, why doesn't [i for i in foo] work?
What about this:
def __iter__(self):
return iter(self.__dict__.items())
Python wants an iterator, not a list (or other list-like/dict-like object)
Remember: a list or dict is not an iterator, an iterator is usually (for easy-understanding) a pointer (cursor) pointing to an item of the list or dict.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With