Learning Iterator Chains

Elderly Beginner · December 20, 2019

On my journey to understanding Python, I met yield keyword. Trying to grasp the idea of using it I start typing some code to generate similar effects, but with the knowledge I already have.

The point is to square values in given list and negate values in a given list. It is simple and I started with:

# first approach: returning changed list
def sq(a):
    for i in range(len(a)):
        a[i] = a[i] * a[i]
    return a


def neg(a):
    for i in range(len(a)):
        a[i] = -a[i]
    return a


data = [1, 2, 3, 4, 5]

sqred = sq(data)
neged = neg(sqred)

It is not Pythonic, so let’s see how yield works:

# second approach: using iterator chain
def icsq(a):
    for i in a:
        yield i * i 


def icneg(a):
    for i in a:
        yield -i


data = [1, 2, 3, 4, 5]
icsqed = list(icsq(data))
icneged = list(icneg(icsqed))

It looks much better and… it’s not Pythonic thou!

As I strongly believe that one day I will find a use for yield keyword it’s not this time. As soon as I used yield I was confused and I felt I was missing something. That’s my favorite sugar of Python:

# third approach: using generator expression with ()
# list comprehension works as well and would be even better in this example
# as generator expression is not used as iterator

data = [1, 2, 3, 4, 5]

gesqed = list(x * x for x in data)
geneged = list(-x for x in gesqed)

It was mind exercise for me inspired by Dan Bader book Python Tricks - 6.7 Iterator Chains.

There was one more solution that came to my mind and I quickly typed a note to myself:

# fourth approach: using decorator
# @wrapper is possible e.g. using it to extend sq function for negating,
# but it is against it's logic.

Twitter, Facebook