Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Assigning "through" an iterator

I have an iterator over a mutable sequence, e.g.

foo = [1, 2, 3, 4, 5]
for bar in foo:

Is there a way to write to the elements in foo by using the reference which is contained in the iterator? The naive assignment:

   bar = 42

does not work of course. Is it possible to use the "behind the curtain" reference to the sequence element which is in the iterator ?

PS: The simple solution with using an index

for i in range(len(a)):
   a[i] = 42

will not work for my case, as I can't expose the container name.

like image 269
Vroomfondel Avatar asked Oct 24 '13 09:10

Vroomfondel


People also ask

How do I use an iterator in Python?

Iterator in Python is an object that is used to iterate over iterable objects like lists, tuples, dicts, and sets. The iterator object is initialized using the iter() method. It uses the next() method for iteration. __next__(): The next method returns the next value for the iterable.

How does __ ITER __ work in Python?

The __iter__() function returns an iterator object that goes through each element of the given object. The next element can be accessed through __next__() function. In the case of callable object and sentinel value, the iteration is done until the value is found or the end of elements reached.

How do you use an iterator in a for loop?

Obtain an iterator to the start of the collection by calling the collection's iterator( ) method. Set up a loop that makes a call to hasNext( ). Have the loop iterate as long as hasNext( ) returns true. Within the loop, obtain each element by calling next( ).


2 Answers

Use enumerate() to generate indices for you in the loop:

for i, bar in enumerate(foo):
    foo[i] = bar + 42
like image 135
Martijn Pieters Avatar answered Sep 27 '22 16:09

Martijn Pieters


From my understanding, your use case is something like this:

class Z:
    def __init__(self):
        self.a, self.b, self.c = 1, 2, 3

    def it(self):
        for x in self.a, self.b, self.c:
            yield x

z = Z()
for x in z.it():
    if x == 1:
       x = 42 # z.a should be 42? - doesn't work!

This isn't possible in python - there's no "pointer" or "reference" data type. You can work around this by yielding a setter function instead of (or along with) the value:

class Z:
    def __init__(self):
        self.a, self.b, self.c = 1,2,3

    def it(self):
        for x in 'abc':
            yield getattr(self, x), lambda y: setattr(self, x, y)

z = Z()
for x, setter in z.it():
    if x == 1:
       setter(42) # works!
like image 26
georg Avatar answered Sep 27 '22 15:09

georg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!