首页 > 解决方案 > 如何使用 operator.itemgetter 来检查过滤器函数而不是 lambda 中的条件?

问题描述

说,我有一个像这样的元组列表

tupleSet=[(0, 2), (3, 4), (5, 7)]

我想获得另一个满足元组第二个元素是偶数条件的元组列表。

>>> [(0, 2), (3, 4)]

我想知道这是否可以使用过滤器函数中的 itemgetter 来完成。

我知道可以使用 lambda

list(filter(lambda x: not x[1]%2,tupleSet))

如果可能的话,我想要一个使用 operator.itemgetter 的等效代码(单行代码)。

我尝试使用

list(filter(operator.itemgetter(1)%2==0,tupleSet))

但我明白了

TypeError: unsupported operand type(s) for %: 'operator.itemgetter' and 'int'

所需输出:

[(0, 2), (3, 4)]

使用 itemgetter 函数

标签: python

解决方案


是的,您可以使用itemgetter(),但不能不使用 a lambda(或def functionname(): ...语句语法来定义可调用对象或其他对象组合)。

的第一个参数filter() 必须是可调用对象。虽然operator.itemgetter(1)本身就是这样一个对象并且可以在 中使用filter(),但该表达式operator.itemgetter(1)%2==0不起作用,因为您不能只%在对象上使用运算符itemgetter(),因此会引发TypeError. 即使它没有这样做,你也会将表达式的结果传递给,所以它会在运行之前被调用一次,这也不是你想要的。operator.itemgetter(1)%2==0filter()filter()

lambda你传入的 ,也是lambda x: not x[1]%2一个可调用对象,即一个函数。它之所以有效,是因为lambda <args>: <expression>语法不会立即调用该<expression>部分,而是返回一个函数对象,因此是一个可调用对象。函数 ( ) 中包含的表达式not x[1]%2仅在调用函数时执行(因此,filter()对于每个元素)。

拼写相同事物的另一种方法是首先使用def语句创建命名函数:

def second_element_is_even(tup):
    return not tup[1] % 2

list(filter(second_element_is_even, tupleSet))

这与带有 的版本完全相同lambda,只是现在函数对象也可以在名称下使用second_element_is_even

如果您必须使用一个itemgetter()对象,那么您将不得不编写一个不同的可调用对象,然后为每个过滤的项目调用,并使用该itemgetter()对象作为工具来产生所需的过滤决策。像一个lambda

get_second = operator.itemgetter(1)
list(filter(lambda x: not get_second(x) % 2, tupleSet))

这不是很有用,因为x[1]它确实更具可读性。

但是,如果您曾经需要特定元素是可变的(有时它必须是元组的第一个,有时是第二个元素,有时它应该是总和),那么itemgetter可以使用一个对象来编码它。您可以生成一个元素甚至函数,该函数接受一个来确定它应该测试什么:

def even_tester(key=None):
    if key is None:
        # identity function, test the value directly
        key = lambda v: v
    def is_even(value):
        return not key(value) % 2
    return is_even

# test if the second element is even
list(filter(even_tester(operator.itemgetter(1)), tupleSet))

# test if the first element is even
list(filter(even_tester(operator.itemgetter(1)), tupleSet))

# test if the sum of the elements is even
list(filter(even_tester(sum), tupleSet))

even_tester()这里的工作原理很像itemgetter():调用它会给你一个新的对象,它本身也可以被调用。它在调用时的作用取决于您传递给even_tester().


推荐阅读