2009-05-10 2 views
1

У меня есть небольшой скрипт python, который я использую каждый день ...... он в основном читает файл, и для каждой строки я в основном применяю различные строковые функции, такие как strip(), replace() и т. Д. ... im constanstly редактирование файла и комментирование для изменения функций. В зависимости от файла, с которым я имею дело, я использую разные функции. Например, я получил файл, где для каждой строки мне нужно использовать line.replace ('', '') и line.strip() ...Определение динамических функций для строки

Каков наилучший способ сделать все это как часть мой сценарий? Поэтому я могу просто сказать присваивание чисел каждой функции и просто сказать, что для каждой строки применяются функции 1 и 4.

ответ

2

Прежде всего, многие строковые функции - в том числе полосы и заменить - это 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.f1, O.f2, O.f3 ... но я предполагаю, что это не дух вашего вопроса.

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} 
2

Если вы настаиваете на номера, вы не можете сделать гораздо лучше, чем Dict (как предполагает гимель) или список функций (с индексами ноль и выше). Однако с именами вам необязательно нужна вспомогательная структура данных (например, предложенная гимелем dict), поскольку вы можете просто использовать getattr для извлечения метода для вызова из самого объекта или его типа. Например .:

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 
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']): 
    ... 
Смежные вопросы