使用functools.partial和字符串方法的替代方法

时间:2014-08-09 15:46:54

标签: python string performance arguments partial

对我的代码进行概要分析表明,split个对象的方法stripstr属于最常被调用的函数。

碰巧我使用的构造如:

with open(filename, "r") as my_file:
    for line in my_file:
        fields = line.strip("\n").split("\t")

并且应用它的一些文件有很多行。

所以我尝试在https://wiki.python.org/moin/PythonSpeed/PerformanceTips中使用“避免点”建议,如下所示:

from functools import partial
split = str.split
tabsplit = partial(split, "\t")
strip = str.strip
endlinestrip = partial(strip, "\n")
def get_fields(tab_sep_line):
    return tabsplit(endlinestrip(tab_sep_line))

with open(filename, "r") as my_file:
    for line in my_file:
        fields = getfields(line)

但是,这为我ValueError: empty separator函数的return行提供了get_fields

经过调查,我理解的是split方法的分隔符是第二个位置参数,第一个是字符串对象本身,这使得functools.partial理解"\t"为要拆分的字符串,我使用"\n".strip(tab_sep_line)的结果作为分隔符。因此错误。

你打算做什么呢?


编辑: 我试图比较三种实现get_fields函数的方法。

方法1:使用普通.strip.split

def get_fields(tab_sep_line):
    return tab_sep_line.strip("\n").split("\t")

方法2:使用lambda

split = str.split
strip = str.strip
tabsplit = lambda s : split(s, "\t")
endlinestrip = lambda s : strip(s, "\n")
def get_fields(tab_sep_line):
    return tabsplit(endlinestrip(tab_sep_line))

方法3:使用Jason S提供的答案

split = str.split
strip = str.strip
def get_fields(tab_sep_line):
    return split(strip(tab_sep_line, "\n"), "\t")

概要分析表示get_fields的累计时间如下:

方法1:13.027

方法2:16.487

方法3:9.714

因此避免使用点会产生影响,但使用lambda似乎会适得其反。

1 个答案:

答案 0 :(得分:3)

建议"避免点"性能是(1)只有在你遇到性能问题时才应该做的事情,即如果它被调用了很多次但是如果实际上需要花费太多时间,那么(2)不能使用partial来解决。

点可能比本地人花费更多时间的原因是python每次都必须执行查找。但是如果您使用partial,则每次时都会有一个额外的函数调用,每次并且添加两个列表时它也会复制和更新字典。你没有获得,你正在失败。

但是,如果你真的想要你能做到:

strip = str.strip
split = str.split
...
fields = split(strip(line), '\t')