简体   繁体   中英

trying to understand lambda

When I do

dict = {'Alice': '7898', 'Beth': '9102', 'Cecil': '3258'}
print filter(lambda x: x, dict['Alice'])

it shows: 7898

When I do the next

dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
print filter(lambda x: x=="2341", dict['Alice'])

it shows:

Why it doesn't show True. How to get True?

filter() does the following: given a function and an iterable (like a list, tuple, etc), passes each item in the list to a function. For each item, the function returns a boolean true or false. If the function returns true on an item, the item is added to a new list.

When filter is finished, it returns the new list with all of the selected items. This allows you to "filter" through a list based on a criteria and select only the items matching the criteria.

A tricky thing is happening here. filter() loops through any iterable. This includes a string. When you pass dict['Alice'] as the object to iterate, it's passing '2341', and running the filter on each character in the string. You could break the filter's logic down as follows:

def matches(x):
    return x == '2341'

result = ''
for char in x:
    if matches(char):
         result += char

print result

This doesn't work, because none of your individual characters equal '2341'.

It looks like your misunderstanding is with filter , to me. You pass a predicate function and an iterable object to filter . It creates a new object containing those items from the first iterable for which the predicate returns a true value (not necessarily True itself, just something that tests as true). The iterable in the two cases is the string '2341' , which means the individual letters are tested. Of course the string '2341' is not equal to any of '2' , ' 3' , '4' , or '1' .

Try it with a tuple and it's easier to see what's going on:

>>> tup = tuple(dict['Alice'])
>>> tup
('7', '8', '9', '8')
>>> filter(lambda x: x, tup)
('7', '8', '9', '8')
>>> tup
('7', '8', '9', '8')
>>> filter(lambda x: x, tup)
('7', '8', '9', '8')
>>> filter(lambda x: x=="2341", tup)
()

Do you want to test if the entry for 'Alice' is '2341'. You can do so via

print dict['Alice'] == '2341'

The issue you are facing is not with the lambda form but with the method filter which is not appropriate in this use case.

In general a lambda form is more or less nothing else than an anonymous function (see eg here ).

Maybe what you're trying to do is:

>>> dic = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
>>> [i for i in dic if dic[i] == '2341']
['Alice']

And if you add other elements with the same value, you'll get all of then in the list

If you just want to call the lambda function you just use it like a function:

print (lambda x: x=="2341")(dict["Alice"])

This gives the expected result (true).

When you use filter , it treats its second argument as a list, so "2341" is treated as a list of characters ['2', '3', '4', '1'] , none of which equals "2341".

Interesting thing I just found out: Python 3 returns filter objects from the filter() function, so the proper use of filter becomes

print( list( filter( lambda x: x, dict['Alice'] ) ) )

And that returns ['2', '3', '4', '1'] which would have avoided the initial confusion.

Normally, one would apply filter to two arguments:

  1. a function
  2. a list (or other iterable object)

filter applies the function to each object in the list and return a list of all the objects for which the function returned True .

In your second example, your first argument is a function, as expected. But your second argument is not a list — it is a string "2341" (the result of looking up "Alice" in the dictionary).

( Edit : I got this next part wrong initially. Thanks to other posters for getting it right.) Filter treats the string like a list, applying the function to each character and keeping only those characters for which it returned True (none of them), resulting in an empty string. Now if you look back at your first example, it has the same problem, and it is only (bad?) luck that the answer was what you expected.

As another poster suggested, perhaps you want to apply your function more directly. In the first example:

(lambda x: x)(dict['Alice'])

In the second example:

(lambda x: x=="2341")(dict['Alice'])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM