CarlLee
CarlLee

Reputation: 4182

Can not understand Python expression

I encoutered some Python function and totally cannot understand its meaning, nor did I know how it works.

def test(data, bot):
    return reduce(lambda a, b: a or b, [i in data['message'] for i in
        ['地震了吗', '地震了么', '地震了?', '地震了?', '地震了吧']])

I know the result is if data['message'] (which is a string value) contains any of these strings ['地震了吗', '地震了么', '地震了?', '地震了?', '地震了吧'], function test will return true.

Upvotes: 1

Views: 150

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121804

You are looking at a list comprehension; for each i it will calculate i in data['message'].

If you were to write this out in a loop instead, it would be:

tmplist = []
for i in ['地震了吗', '地震了么', '地震了?', '地震了?', '地震了吧']:
    tmplist.append(i in data['message'])

So, for each string in the list, test the boolean expression i in data['message'] and add the result (True or False) in `tmplist.

The reduce() function then returns the equivalent of:

tmplist[0] or tmplist[1] or tmplist[2] or ... or tmplist[len(tmplist)-1]

but expressed in a more tortuous manner. reduce(lambda a, b: a or b, sequence) starts with sequence[0] and sequence[1] as a and b, then takes the result of the lambda as a and the next element in sequence as b, and repeats this until all elements in senquence have been processed.

A friendlier way to write this would be to use any() instead:

return any(i in data['message']
    for i in ['地震了吗', '地震了么', '地震了?', '地震了?', '地震了吧'])

any() is actually more efficient; it'll run the generator and will stop immediately when a match is found; if data['message'] contains '地震了吗' only one test will be performed.

Upvotes: 13

Related Questions