使用字符串方法的functools.partial替代方案
我的代码分析显示,str
对象的split
和strip
方法是被调用次数最多的函数之一。
我使用了一些这样的代码:
with open(filename, "r") as my_file:
for line in my_file:
fields = line.strip("\n").split("\t")
而且,有些文件的行数非常多。
所以我尝试按照这个链接里的建议,尽量避免使用点(即方法调用),如下所示:
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)
然而,这导致我的get_fields
函数在return
这一行出现了ValueError: empty separator
的错误。
经过调查,我了解到split
方法的分隔符是第二个参数,第一个参数是字符串对象本身。这让functools.partial
把"\t"
理解成了要被分割的字符串,而我使用"\n".strip(tab_sep_line)
的结果作为分隔符。因此出现了错误。
你有什么建议可以替代这个做法吗?
编辑:我尝试比较了三种实现get_fields
函数的方法。
方法一:使用普通的.strip
和.split
def get_fields(tab_sep_line):
return tab_sep_line.strip("\n").split("\t")
方法二:使用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))
方法三:使用Jason S提供的答案
split = str.split
strip = str.strip
def get_fields(tab_sep_line):
return split(strip(tab_sep_line, "\n"), "\t")
分析结果显示,get_fields
的累计时间如下:
方法一:13.027
方法二:16.487
方法三:9.714
所以,避免使用点确实有区别,但使用lambda
似乎是得不偿失。
1 个回答
3
关于“避免使用点(.)”来提高性能的建议,其实有两个要点:第一,只有在你真的遇到性能问题的时候才需要考虑这个问题,也就是说,不是因为某个东西被调用很多次就一定要担心,而是要看它是否真的“耗时过长”;第二,使用partial
并不能解决这个问题。
之所以使用点的操作会比使用局部变量慢,是因为每次使用点的时候,Python都需要去查找这个属性。但如果你使用partial
,那么每次调用时不仅会多一次函数调用,还会每次都复制和更新一个字典,并且还要添加两个列表。这样做其实是得不偿失,反而会更慢。
不过,如果你真的想这么做,可以试试:
strip = str.strip
split = str.split
...
fields = split(strip(line), '\t')