否定`operator.attrgetter`

时间:2016-06-21 09:09:52

标签: python list-comprehension itertools

我想使用itertool.groupbyresult = process('Am G C') assert result == [(2, 'Am'), (20, ' '), (1, 'G'), (10, ' '), (1, 'C')] 按空格分割文本字符串,保留文本之间的空格数。这是预期的行为:

attrgetter

正如我所说,我想使用text = '''Am G C''' processed=((k, list(l))for k, l in groupby(text, attrgetter("isspace"))) result = [(len(l), "".join(l)) if k else (len(l), " ") for k, l in processed] ,因为我发现它比使用lambda更加pythonic。我能做到:

[(1, 'A'), (1, 'm'), (20, '                    '), (1, 'G'), (10, '          '), (1, 'C')]

但这会回来:

from operator import neg, attrgetter
text = '''Am                    G          C'''
processed = ((k,list(l)) for k,l in groupby(text, neg(attrgetter("isspace"))))
result = [(len(l), "".join(l)) if k else (len(l), " ") for k, l in processed]

我需要的是完全相反的,我试过了:

attrgetter

这引发:

  

TypeError:一元的坏操作数类型 - :'operator.attrgetter'

如何为了关键功能目的否定def foo(): Unit { a() b() } 返回的值?

2 个答案:

答案 0 :(得分:4)

operator.attrgetter不会直接作为关键功能发挥作用。 GET /resources/999 Accept: application/vnd.yourcompany.resourcetype+json # Receiving full representation of /resources/999 GET /resources/999 Accept: application/vnd.yourcompany.resourcetype.light+json # Receiving light representation of /resources/999 GET /resources/999 Accept: application/vnd.yourcompany.resourcetype.name_price+json # Receiving "name" and "price" from /resources/999 只会获取attrgetter("isspace")(x)的{​​{1}}属性,同时您还需要调用它:

"isspace"

您可以改为使用str.isspace

x

答案 1 :(得分:2)

不,您不能对attrgetterneg运算符的任何其他函数执行反函数。首先,neg代表否定;例如neg(x)< => -x。这适用于False结果0; True => -1。布尔否定为operator.not_。但即便如此,这对于帮助你否定回报价值也无济于事 - 甚至否定也无助于你。

相反,您应该将str.isspace传递给groupby; str.ispace是一个未绑定的方法 - 接受str类型的参数。

您在这里看到的是,attrgetter('isspace')的返回值是以每个单个字符作为值调用的。每次调用都会返回绑定实例方法:

>>> attrgetter('isspace')('a')
<built-in method isspace of str object at 0x7fb204de5110>

由于这些绑定方法中的每一个都绑定到不同的实例,它们必然彼此不同,并且不能相互比较,这就是为什么您的代码不能达到您期望的效果。要获得实际值,您必须再次调用此方法:

>>> attrgetter('isspace')('a')
False

对于这种情况,我完全放弃了itertools。这是一个纯文本任务,因此可以使用正则表达式和re模块。

re.split已达到你想要的90%时,甚至无需处理这个字符:

>>> import re
>>> s = 'Am                    G          C'
>>> parts = re.split('(\s+)', s)
>>> parts
['Am', '                    ', 'G', '          ', 'C']

然后,只需使用列表推导使这些变为长度,字符串元组:

>>> [(len(i), i) for i in parts]
[(2, 'Am'), (20, '                    '), (1, 'G'), (10, '          '), (1, 'C')]

即,re.split按给定的正则表达式分割。 \s+匹配一个或多个空白字符。通常会丢弃分隔符,但如果正则表达式包含子组(...),则该子组的内容也会保留在匹配中。