将动态函数定义为字符串

时间:2009-05-10 07:44:23

标签: python

我有一个小python脚本,我每天都使用......它基本上读取一个文件,对于每一行我基本上应用不同的字符串函数,如strip(),replace()等....我常常编辑文件和注释以更改功能。根据我正在处理的文件,我使用不同的功能。例如,我有一个文件,每行,我需要使用line.replace('','')和line.strip()......

将所有这些作为我脚本的一部分的最佳方法是什么?所以我可以说为每个函数分配数字,然后说每行应用函数1和4。

4 个答案:

答案 0 :(得分:2)

可以将字符串操作映射到数字:

>>> import string
>>> ops = {1:string.split, 2:string.replace}
>>> my = "a,b,c"
>>> ops[1](",", my)
[',']
>>> ops[1](my, ",")
['a', 'b', 'c']
>>> ops[2](my, ",", "-")
'a-b-c'
>>> 

但是,操作的字符串描述可能更具可读性。

>>> ops2={"split":string.split, "replace":string.replace}
>>> ops2["split"](my, ",")
['a', 'b', 'c']
>>> 

注意: 您可以使用string类型获得相同的效果,而不是使用str模块。

>>> ops={1:str.split, 2:str.replace}

答案 1 :(得分:2)

如果你坚持使用数字,你不能比dict(如gimel建议的那样)或函数列表(索引为零及以上)做得更好。但是,对于名称,您不一定需要辅助数据结构(例如gimel建议的dict),因为您可以简单地使用getattr来检索从对象本身或其类型调用的方法。 E.g:

def all_lines(somefile, methods):
  """Apply a sequence of methods to all lines of some file and yield the results.
  Args:
    somefile: an open file or other iterable yielding lines
    methods: a string that's a whitespace-separated sequence of method names.
        (note that the methods must be callable without arguments beyond the
         str to which they're being applied)
  """
  tobecalled = [getattr(str, name) for name in methods.split()]
  for line in somefile:
    for tocall in tobecalled: line = tocall(line)
    yield line

答案 2 :(得分:2)

首先,许多字符串函数(包括strip和replace)都是deprecated。以下答案使用字符串方法。 (而不是string.strip(" Hello "),我使用等效的" Hello ".strip()。)

这里有一些代码可以简化你的工作。以下代码假定您在字符串上调用的方法,该方法将返回另一个字符串。

class O(object):
    c = str.capitalize
    r = str.replace
    s = str.strip

def process_line(line, *ops):
    i = iter(ops)
    while True:
        try:
            op = i.next()
            args = i.next()
        except StopIteration:
            break
        line = op(line, *args)
    return line

存在O类,因此高度缩写的方法名称不会污染您的命名空间。如果要添加更多字符串方法,可以使用与给定格式相同的格式将它们添加到O

process_line函数是所有有趣事情发生的地方。首先,这里是参数格式的描述:

  • 第一个参数是要处理的字符串。
  • 其余参数必须成对出现。
    • 该对的第一个参数是字符串方法。在此处使用缩短的方法名称。
    • 该对的第二个参数是一个列表,表示该特定字符串方法的参数。

process_line函数返回执行所有这些操作后出现的字符串。

以下是一些示例代码,展示了如何在自己的脚本中使用上述代码。我已将process_line的参数分隔为多行,以显示参数的分组。当然,如果您只是在日常脚本中使用此代码,那么您可以将所有参数压缩到一行;这实际上使它更容易阅读。

f = open("parrot_sketch.txt")
for line in f:
    p = process_line(
        line,
        O.r, ["He's resting...", "This is an ex-parrot!"],
        O.c, [],
        O.s, []
    )
    print p

当然,如果你非常特别想使用数字,你可以命名你的函数O.f1O.f2O.f3 ......但我认为这不是精神你的问题。

答案 3 :(得分:0)

要将名称(或数字)映射到不同的字符串操作,我会执行类似

的操作
OPERATIONS = dict(
    strip = str.strip,
    lower = str.lower,
    removespaces = lambda s: s.replace(' ', ''),
    maketitle = lamdba s: s.title().center(80, '-'),
    # etc
)

def process(myfile, ops):
    for line in myfile:
        for op in ops:
            line = OPERATIONS[op](line)
        yield line

你喜欢这个

for line in process(afile, ['strip', 'removespaces']):
    ...