Python 求反`operator.attrgetter`

Python 求反`operator.attrgetter`,python,list-comprehension,itertools,Python,List Comprehension,Itertools,我想使用operator.attrgetter和itertool.groupby将文本字符串按空格分割,保留文本之间的空格数。这是预期的行为: result = process('Am G C') assert result == [(2, 'Am'), (20, ' '), (1, 'G'), (10, ' '), (1, 'C')] 正如我所说,我想使用attrgetter,因为我发现它比使用lambda更具python风格。我可以做

我想使用
operator.attrgetter
itertool.groupby
将文本字符串按空格分割,保留文本之间的空格数。这是预期的行为:

result = process('Am                    G          C')
assert result == [(2, 'Am'), (20, ' '), (1, 'G'), (10, ' '), (1, 'C')]
正如我所说,我想使用
attrgetter
,因为我发现它比使用lambda更具python风格。我可以做到:

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]
但这将再次出现:

[(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]
这引发了:

TypeError:一元数的操作数类型错误-:“operator.attrgetter”

对于键函数,如何对从
attrgetter
返回的值求反?

在这里不会直接用作键函数
attrgetter(“isspace”)(x)
将只获取
x
“isspace”
属性,同时您还需要调用它:

>>> attrgetter("isspace")(" ")
<built-in method isspace of str object at 0x7f30c4301ab0>
>>> attrgetter("isspace")(" ")()
True
不会直接作为一个关键功能在这里工作
attrgetter(“isspace”)(x)
将只获取
x
“isspace”
属性,同时您还需要调用它:

>>> attrgetter("isspace")(" ")
<built-in method isspace of str object at 0x7f30c4301ab0>
>>> attrgetter("isspace")(" ")()
True

不可以,您不能使用
attrgetter
的反向函数,也不能使用
neg
运算符生成任何其他函数。首先,
neg
代表否定;e、 g.
neg(x)
-x
。应用于
False
的结果是
0
<代码>真=>
-1
。布尔求反是
运算符。而不是
。但即使这样,这对否定返回值也没有什么帮助——事实上,即使否定也无助于你

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

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

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

在这种情况下,我会完全抛弃
itertools
。这是一个纯文本任务,因此正则表达式和模块是一个不错的选择

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+匹配一个或多个空白字符。通常会丢弃分隔符,但如果正则表达式包含子组
(…)
,则该子组的内容也会保留在匹配中

否,您不能使用
attrgetter
或任何其他带有
neg
运算符的函数生成反转函数。首先,
neg
代表否定;e、 g.
neg(x)
-x
。应用于
False
的结果是
0
<代码>真=>
-1
。布尔求反是
运算符。而不是
。但即使这样,这对否定返回值也没有什么帮助——事实上,即使否定也无助于你

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

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

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

在这种情况下,我会完全抛弃
itertools
。这是一个纯文本任务,因此正则表达式和模块是一个不错的选择

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+匹配一个或多个空白字符。通常会丢弃分隔符,但如果正则表达式包含子组
(…)
,则该子组的内容也会保留在匹配中

只需编写您自己的函数来反转它并使用它。我认为在不使用lambda的情况下,最接近的是
。\uu____
。在这个特定的问题中,您实际上不需要在这里否定函数,只需在if/else表达式中否定条件即可。因此,如果y-else z变成
x,如果不是y-else z
。例如,
result=[(len(l),“”.join(l))如果不是k,则为k,l在处理中]
。您也可以在
attrgetter(“isspace”)
上使用
str.isspace
。这不起作用,因为组是颠倒的,但这就是您想要的?你只是在另一个地方使用否定。在应用否定的地方,不影响
groupby
。您可以执行
(…groupby(text,(lambda x:not x.isspace()))
,后跟
[x if y else z]
。我做
(…groupby(text,str.isspace))
然后是
[x if not y else z]
只需编写自己的函数来反转它并使用它。我认为不使用lambda最接近的方法是
”。\uu ne\uuu
。在这个特定的问题中,您不需要在这里否定函数,只需对if/else表达式中的条件求反即可。因此,如果y-else z变成
x,如果不是y-else z
。例如,
result=[(len(l),“”.join(l))如果不是k,则为k,l在处理中]
。您也可以在
attrgetter(“isspace”)
上使用
str.isspace
。这不起作用,因为组是颠倒的,但这就是您想要的?你只是在另一个地方使用否定。在应用否定的地方,不影响
groupby
。您可以执行
(…groupby(text,(lambda x:not x.isspace()))
,后跟
[x if y else z]
。我做