为啥 foo = filter(...) 返回一个 <filter object>,而不是一个列表? [复制]

Posted

技术标签:

【中文标题】为啥 foo = filter(...) 返回一个 <filter object>,而不是一个列表? [复制]【英文标题】:Why does foo = filter(...) return a <filter object>, not a list? [duplicate]为什么 foo = filter(...) 返回一个 <filter object>,而不是一个列表? [复制] 【发布时间】:2016-01-15 10:20:15 【问题描述】:

在 Python IDLE 3.5.0 shell 中工作。根据我对内置“过滤器”函数的理解,它返回列表、元组或字符串,具体取决于您传递给它的内容。那么,为什么下面的第一个分配有效,而第二个无效('>>> 只是交互式 Python 提示)

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

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

【问题讨论】:

在我的机器上,help(filter) 说它返回一个迭代器,而不是列表、元组或字符串。您可能正在查看旧版本 Python 的文档。在任何情况下,您的filter 表达式即使在旧版本中也不起作用,因为filter 的第一个参数必须是可调用的,而greetings() 返回的值不是可调用的。 我使用的是一个旧教程,它没有说明 Python 的版本。谢谢凯文....虽然我不明白(只是从这里开始:-)...你的意思是:“因为 filter 的第一个参数必须是可调用的,并且 greetings() 返回的值不是一个可调用的。” 接下来你让我自学什么是可调用对象。在论坛和其他地方都找到了一些主题。再次感谢! (试图编辑以前的评论,但 *** 不允许... “不允许”?这当然是允许的——你能够存储返回值(没有引发异常);该值不是您所期望的。这里的原标题有些误导。 【参考方案1】:

filter 期望得到一个函数和它可以迭代的东西。该函数应为迭代中的每个元素返回 True 或 False。在您的特定示例中,您要执行的操作类似于以下内容:

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

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

请注意,在 Python 3 中,可能需要使用 list(filter(greetings, ["hello", "goodbye"])) 才能获得相同的结果。

【讨论】:

【参考方案2】:

来自文档

注意filter(function, iterable) 等价于[item for item in iterable if function(item)]

在python3中,而不是返回一个列表;过滤器,映射返回一个可迭代的。您的尝试应该适用于 python2,但不适用于 python3

很明显,你得到了一个过滤器对象,把它变成一个列表。

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

【讨论】:

【参考方案3】:

请查看filter 的示例实现以了解它在 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))

以下是如何使用filtermy_filter 生成器的示例:

>>> greetings = 'hello'
>>> spoken = my_filter(greetings.__contains__, ('hello', 'goodbye'))
>>> print('\n'.join(spoken))
hello

【讨论】:

【参考方案4】:

查看filter(function, iterable) 的python 文档(来自here):

iterablefunction 返回 true 的那些元素构造一个迭代器。

所以为了得到一个列表,你必须使用列表类:

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

但这可能不是您想要的,因为它试图在您的输入列表的值上调用greetings() 的结果,即“hello”,这将不起作用。在这里,迭代器类型也发挥了作用,因为在您使用它们之前不会生成结果(例如通过在其上调用list())。所以一开始你不会收到错误,但是当你尝试使用shesaid 做某事时,它会停止工作:

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

如果您想检查列表中的哪些元素等于“hello”,您必须使用以下内容:

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

(我将您的函数放入 lambda,请参阅 Randy C 对“正常”函数的回答)

【讨论】:

请注意,由于(),第一行shesaid不会在输入列表的值上调用greetings——它会尝试调用greetings() 返回的值。所以它会尝试调用"hello"(字符串),就好像它是一个函数一样。 感谢 DSM,-是的,您的评论证实了 TobiMarg 的回复让我对正在发生的事情的确切理解。清除...一旦得到它! :-) @DSM 谢谢!那是一个重要的错误。我现在修好了。【参考方案5】:

它返回&lt; filter object &gt;的原因是,filter是类而不是内置函数。

help(filter) 你会得到以下信息: 关于内置模块中的类过滤器的帮助:

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.

【讨论】:

以上是关于为啥 foo = filter(...) 返回一个 <filter object>,而不是一个列表? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥带赋值的三元运算符不返回预期的输出?

为啥 Scheme `filter` 表单不能“按顺序”处理列表元素?

为啥代理下的getContextPath()返回的是HttpServlet内部的内部路径,而不是Filter内部的路径?

为啥这个函数返回垃圾值

为啥移动赋值运算符应该返回对 *this 的引用 [重复]

为啥prometheus中increase()会返回1.33的值?