0

In datatstructures.py, there is a method values():

def values(self):
    """Iterate over all values."""
    for item in self:
        yield item[0]

self is an instance of the class; how can it be iterated over?

2
  • Possible duplicate of Python iterating through object attributes Commented Jan 24, 2016 at 17:58
  • Not a duplicate. My question is not How to but rather How can (as in: how can it be possible). Commented Jan 24, 2016 at 18:03

4 Answers 4

2

The class which the given method belongs to extends ImmutableList which is iterable, thus the method can iterate on the class.

Sign up to request clarification or add additional context in comments.

1 Comment

What defines ImmutableList as iterable? I see now __iter__ method.
1

Simple, it has to implement __iter__ method, e.g.

class Test:
    def __iter__(self):
        yield 1
        yield 2

>>> instance = Test()
>>> for val in instance:
...     print val
...
1
2

Comments

1

If the object in question is Iterable it can be iterated. This is how lists, dicts, and other sequences are designed.

Comments

1

My question is not How to but rather How can (as in: how can it be possible)

self refers to the actual tangible object you deal with, classes are more like their interface (don't interpret this too strictly); if an instances' class defines a __iter__ (or __getitem__) method they can be iterated over in a for loop. PEP 234 deals with the semantics and implementation of iterators.

In your specific case the function is a generator which has nothing to do with the __iter__ method, it simply transforms the values function to a generator in order to support iteration of the form:

for i in instance.values(): # do stuff

If the object doesn't define an __iter__ it won't be able to be iterated over, as an example:

class myfoo:
    def func(self):
        for i in range(10): yield i

f = myfoo()

The instance f is now not iterable:

for i in f: print(i) # TypeError

On the other hand, we can use func in a for loop:

for i in f.func(): print(i, end=" ")
0 1 2 3 4 5 6 7 8 9

Changing func to __iter__ changes the picture, now the instance f is iterable:

class myfoo:
    def __iter__(self):
        for i in range(10): yield i

f = myfoo()

Iterating through f is done intuitively with:

for i in f: print(i, end=" ")
0 1 2 3 4 5 6 7 8 9

Asking why, as in, how can this be possible is like asking why can strings be multiplied with "s" * 4. This is the way things were implemented because it just made sense as a way of handling the common case of looping through the contents of a container. Don't overthink things, it isn't necessary.

1 Comment

@Pyderman You're welcome, good for you for digging in the source code of projects and trying to understand how they work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.