Trying to understand the function of reduce in python

I recently received an answer from the stackoverflow fellow on my previous question and I tried to inquire more in order to understand the function but somehow no response so I wish to ask it here.

I wanted to know what is the k and v that used in the lambda represent? I thought it was representing like this......

k = dictionary ?
v = string ? # Did I understand it correctly?

dictionary = {"test":"1", "card":"2"}
string = "There istest at the cardboards"

from functools import reduce
res = reduce(lambda k, v: k.replace(v, dictionary[v]), dictionary, string)

since we use lambda then it loop each of the element within both of these variables. But why k.replace? Isnt that a dictionary? Should It be v.replace? Somehow this method works. I wish someone could explain to me how this work and please more details if possible. Thank you!

Upvotes: 1

Views: 129

Answers (1)

torek
torek

Reputation: 490078

reduce is equivalent to repeatedly calling a function.

The function in this case is a lambda, but a lambda is just an anonymous function:

def f(k, v):
    return k.replace(v, dictionary[v])

The definition of reduce itself is (almost—the None default here is not quite right, nor the len test):

def reduce(func, seq, initial=None):
    if initial is not None:
       ret = initial
       for i in seq:
           ret = func(ret, i)
       return ret
    # initial not supplied, so sequence must be non-empty
    if len(seq) == 0:
        raise TypeError("reduce() of empty sequence with no initial value")
    first = True
    for i in seq:
        if first:
            ret = i
            first = False
        else:
            ret = func(ret, i)
    return ret

So, ask yourself what this would do when called on your lambda function. The:

for i in dictionary

loop will iterate over each key in the dictionary. It will pass that key, along with the stored ret (or the initial argument for the first call), to your function. So you'll get each key, plus the string value that's initially "There istest at the cardboards", as your v (key from dictionary, called i in the expansion of reduce) and k (long string, called ret in the expansion of reduce) arguments.

Note that k is the full text string, not the string used as the key in the dictionary, while v is the word that is the key in the dictionary. I've used the variable names k and v here only because you did too. As noted in a comment, text and word might be better variable names in either the expanded def f(...) or the original lambda function.

Trace your code execution

Try the same code, except that instead of just:

def f(k, v):
    return k.replace(v, dictionary[v])

you write it as:

def f(text, word):
    print("f(text={!r}, word={!r})".format(text, word))
    replacement = dictionary[word]
    print("  I will now replace {!r} with {!r}".format(word, replacement))
    result = text.replace(word, replacement)
    print("  I got: {!r}".format(result))
    return result

Run the functools.reduce function over function f with dictionary and string as the other two arguments and observe the output.

Upvotes: 1

Related Questions