python: функция замены re.sub не принимает дополнительных аргументов - как избежать глобальной переменной? - PullRequest
7 голосов
/ 23 октября 2011

Я пытаюсь увеличить все метки времени (в формате «ЧЧ: ММ: СС») в текстовом файле на количество секунд, указанное в параметре командной строки для моей программы.

Вот упрощенная версия моих усилий на данный момент:

import re
from datetime import datetime, timedelta

time_diff = timedelta(seconds=10)

def replace_time(matchobj):
    if matchobj.group(1) not in [None, '']:
       return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")

print re.sub('(\d\d:\d\d:\d\d)', replace_time, "01:27:55")

Это отлично работает: результат запуска - 01:28:05, это как раз то, что я хочу.

Однако я слышал, что я должен использовать глобальные переменные как можно меньше. Поэтому мне было интересно, есть ли простой способ передать time_diff в качестве аргумента replace_time вместо использования глобальной переменной.

Я попробовал очевидное, но не получилось:

def replace_time(matchobj, time_diff):
    if matchobj.group(1) not in [None, '']:
       return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")

time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', replace_time(matchobj, time_diff), "01:27:55")

с этой ошибкой: NameError: name 'matchobj' is not defined, поэтому я не могу передать matchobj напрямую.

Я посмотрел стандартную страницу и стандартную информацию , но не могу найти там нужную мне информацию. Как я могу избежать использования глобальной переменной здесь? Можно ли как-то передать дополнительный аргумент функции replace_time? Заранее спасибо.

Ответы [ 2 ]

12 голосов
/ 23 октября 2011

Вы можете обернуть функцию в замыкание следующим образом:

def increment_by(time_diff):
    def replace_time(matchobj):
        if matchobj.group(1) not in [None, '']:
            return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")
    return replace_time

time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', increment_by(time_diff), "01:27:55")

Или вы можете использовать partial из stdlib следующим образом:

from functools import partial

def replace_time(time_diff, matchobj):
    if matchobj.group(1) not in [None, '']:
        return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")

time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', partial(replace_time, time_diff), "01:27:55")
1 голос
/ 23 октября 2011

В вашем текущем подходе нет ничего плохого. time_diff записывается только один раз, и все последующие обращения считываются. В результате это постоянная модуля.

Вы сталкиваетесь с проблемами с общим глобальным состоянием, когда у вас есть несколько потоков, обращающихся к объекту, и по крайней мере один из потоков пишет. Этого здесь не происходит, и вам не о чем беспокоиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...