python - 如何使用 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 函数
解决方案
是的,您可以使用itemgetter()
,但不能不使用 a lambda
(或def functionname(): ...
语句语法来定义可调用对象或其他对象组合)。
的第一个参数filter()
必须是可调用对象。虽然operator.itemgetter(1)
本身就是这样一个对象并且可以在 中使用filter()
,但该表达式operator.itemgetter(1)%2==0
不起作用,因为您不能只%
在对象上使用运算符itemgetter()
,因此会引发TypeError
. 即使它没有这样做,你也会将表达式的结果传递给,所以它会在运行之前被调用一次,这也不是你想要的。operator.itemgetter(1)%2==0
filter()
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()
.
推荐阅读
- gatsby - 基于 gatsby starter blog 在 Netlify 上为我的 Gatsby 应用程序部署失败
- powershell - Powershell 命令作为 Ansible 中的变量
- android - minSdkVersion 21 是否只允许 Android >= 5 用户从商店下载应用程序?
- java - 如果我向服务器发送带有参数的 get 请求,我会收到 Postman 不允许的 405 方法
- android - 设计安卓用户界面
- sql - 将不同表中的多个列合并为一个
- python - Matplotlib如何调整点位置
- r - “无法将对象转换为函数”与 mutate
- nativescript - 强制焦点到 ListView 中的某个索引
- python - get_legend_handles_labels() 不返回新的图例数据