2

I saw this code in here: https://docs.python.org/3/library/itertools.html?highlight=groupby#itertools.groupby

class groupby:
    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
    def __init__(self, iterable, key=None):
        if key is None:
            key = lambda x: x
        self.keyfunc = key
        self.it = iter(iterable)
        self.tgtkey = self.currkey = self.currvalue = object()
    def __iter__(self):
        return self
    def __next__(self):
        self.id = object()
        while self.currkey == self.tgtkey:
            self.currvalue = next(self.it)    # Exit on StopIteration
            self.currkey = self.keyfunc(self.currvalue)
        self.tgtkey = self.currkey
        return (self.currkey, self._grouper(self.tgtkey, self.id))
    def _grouper(self, tgtkey, id):
        while self.id is id and self.currkey == tgtkey:
            yield self.currvalue
            try:
                self.currvalue = next(self.it)
            except StopIteration:
                return
            self.currkey = self.keyfunc(self.currvalue)

In the condition of while self.id is id and self.currkey == tgtkey:, I want know what kind of condition will cause self.id is id to become False?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Afish
  • 21
  • 1
  • can you explain why you need that. I am not coming of as rude but even though you have tried to explain the problem i am still not getting it – Roushan Singh Jun 01 '19 at 13:59
  • Another call to next is the only way you can do it. If you call next before the previous iterator is exhausted, you will run into this condition. – Mad Physicist Jun 01 '19 at 14:01
  • @Roushan. It's an example worth learning from, which is why the official docs provide it. The logic is definitely not immediately apparent. – Mad Physicist Jun 01 '19 at 14:03
  • This may help as additional reading: https://stackoverflow.com/questions/28306371/what-is-object-good-for – benvc Jun 01 '19 at 14:12
  • @MadPhysicist I know call to next until iterator runs of item so that it raises StopIteration . But how do you know he needs it. Also if his needs are somewhat else it may be a bad thing to call next since it changes state of the generator. I hope you would also understand not only i have read the docs but also have read the official python code written in C. The User needs need to be know before any solution could be provided – Roushan Singh Jun 01 '19 at 14:15
  • @Roushan. I don't think you're understanding what OP is asking. – Mad Physicist Jun 01 '19 at 22:46

1 Answers1

1

The condition while self.id is id and self.currkey == tgtkey: reads roughly as "while the user hasn't called next again, and we are in the same group:". self.id is an attribute set by __next__. The local reference id is the reference in _grouper to what self.id was when it got called. Since every call to next generates a new object, the check is equivalent to asking if __next__ has been called since grouper started.

Remember that the groupby object does not have to operate on stored sequences. The input can be a lazy generator. Notice that the functions always read ahead to ensure that the next item is in the current group, and only yield it if it is. The first part of __next__ consumes the remainer of the iterator until the next group starts, to fulfill exactly that part of the contract in case you ask for the next group before the current one is consumed.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264