Why does foo = filter(…) return a <filter object>, not a list?

Question:

Working in Python IDLE 3.5.0 shell. From my understanding of the builtin “filter” function it returns either a list, tuple, or string, depending on what you pass into it. So, why does the first assignment below work, but not the second (the ‘>>>’s are just the interactive Python prompts)

>>> def greetings():
    return "hello"

>>> hesaid = greetings()
>>> print(hesaid)
hello
>>> 
>>> shesaid = filter(greetings(), ["hello", "goodbye"])
>>> print(shesaid)
<filter object at 0x02B8E410>
Asked By: Margarita

||

Answers:

filter expects to get a function and something that it can iterate over. The function should return True or False for each element in the iterable. In your particular example, what you’re looking to do is something like the following:

In [47]: def greetings(x):
   ....:     return x == "hello"
   ....:

In [48]: filter(greetings, ["hello", "goodbye"])
Out[48]: ['hello']

Note that in Python 3, it may be necessary to use list(filter(greetings, ["hello", "goodbye"])) to get this same result.

Answered By: Randy

From the documentation

Note that filter(function, iterable) is equivalent to [item for item in iterable if function(item)]

In python3, rather than returning a list; filter, map return an iterable. Your attempt should work on python2 but not in python3

Clearly, you are getting a filter object, make it a list.

shesaid = list(filter(greetings(), ["hello", "goodbye"]))
Answered By: Ahsanul Haque

Please see this sample implementation of filter to understand how it works in Python 3:

def my_filter(function, iterable):
    """my_filter(function or None, iterable) --> filter object

    Return an iterator yielding those items of iterable for which function(item)
    is true. If function is None, return the items that are true."""
    if function is None:
        return (item for item in iterable if item)
    return (item for item in iterable if function(item))

The following is an example of how you might use filter or my_filter generators:

>>> greetings = {'hello'}
>>> spoken = my_filter(greetings.__contains__, ('hello', 'goodbye'))
>>> print('n'.join(spoken))
hello
Answered By: Noctis Skytower

Have a look at the python documentation for filter(function, iterable) (from here):

Construct an iterator from those elements of iterable for which function returns true.

So in order to get a list back you have to use list class:

shesaid = list(filter(greetings(), ["hello", "goodbye"]))

But this probably isn’t what you wanted, because it tries to call the result of greetings(), which is “hello”, on the values of your input list, and this won’t work. Here also the iterator type comes into play, because the results aren’t generated until you use them (for example by calling list() on it). So at first you won’t get an error, but when you try to do something with shesaid it will stop working:

>>> print(list(shesaid))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable

If you want to check which elements in your list are equal to “hello” you have to use something like this:

shesaid = list(filter(lambda x: x == "hello", ["hello", "goodbye"]))

(I put your function into a lambda, see Randy C’s answer for a “normal” function)

Answered By: TobiMarg

the reason why it returns < filter object > is that, filter is class instead of built-in function.

help(filter) you will get following:
Help on class filter in module builtins:

class filter(object)
 |  filter(function or None, iterable) --> filter object
 |  
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.
 |  
 |  Methods defined here:
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __reduce__(...)
 |      Return state information for pickling.
Answered By: JordanChina