Повторный вызов функции с небольшими изменениями - PullRequest
0 голосов
/ 16 сентября 2018

У меня есть функция с именем get_next_train:

def get_next_train(params):
    res =requests.get(base, params=params)
    parsed_json = res.json()

    #Zeiten aus parsed_json extrahieren
    time_strings = [d["from"]["prognosis"]["departure"]
        for d in parsed_json["connections"]]

    #String, um Zeiten in time_strings nach ISO 8601 zu parsen
    iso_format = "%Y-%m-%dT%H:%M:%S%z"

    # Time Strings zu datetime Objekten konvertieren
    times = [datetime.strptime(ts, iso_format) 
        for ts in time_strings if ts is not None]

    # Checken, ob times leer sind
    if not times:
    return None # CHANGE: return None if no times found

    #Zeitzone der ersten zeit in Times speichern
    tz = times[0].tzinfo

    #jetztige Zeit mit Zeitzone tz, Mikrosekunden löschen
    nowtime = datetime.now(tz).replace(microsecond=0)


    time = min(t for t in times[0:3] if t > nowtime) # CHANGE: use min
    return time, time - nowtime

Я хочу, чтобы это было выполнено дважды: в первый раз, как сейчас. Но во второй раз time_strings должно быть таким:

time_strings = [d["from"]["departure"]
    for d in parsed_json["connections"]]

Я пробовал множество способов сделать это, но каждый раз терпел неудачу. Наиболее распространенная ошибка:

имя 'parsed_json' не определено.

Конечно, я мог бы просто скопировать и вставить весь этот код и изменить нужный мне бит, но есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Вы можете попробовать добавить второй параметр при вызове функции:

def get_next_train(params, flag):
res =requests.get(base, params=params)
parsed_json = res.json()

#Zeiten aus parsed_json extrahieren
if (flag):
    time_strings = [d["from"]["prognosis"]["departure"]
        for d in parsed_json["connections"]]
else:
    time_strings = [d["from"]["departure"]
        for d in parsed_json["connections"]]        

#String, um Zeiten in time_strings nach ISO 8601 zu parsen
iso_format = "%Y-%m-%dT%H:%M:%S%z"

# Time Strings zu datetime Objekten konvertieren
times = [datetime.strptime(ts, iso_format) 
    for ts in time_strings if ts is not None]

# Checken, ob times leer sind
if not times:
return None # CHANGE: return None if no times found

#Zeitzone der ersten zeit in Times speichern
tz = times[0].tzinfo

#jetztige Zeit mit Zeitzone tz, Mikrosekunden löschen
nowtime = datetime.now(tz).replace(microsecond=0)


time = min(t for t in times[0:3] if t > nowtime) # CHANGE: use min
return time, time - nowtime 

Здесь параметр 'flag' - это просто логическое значение, но может быть любым, что вы хотите ...

0 голосов
/ 16 сентября 2018

Инкапсулируйте то, что остается прежним.Инкапсулируйте то, что меняется.

Вы можете определить две разные функции для получения временных строк.Один, чтобы получить прогноз:

def time_strings_from_prognosis(json):
    return [d["from"]["prognosis"]["departure"]
            for d in json["connections"]]

, а другой, чтобы получить другой:

def time_strings_other(json):
    return [d["from"]["departure"]
            for d in json["connections"]]

Затем передайте функцию, чтобы получить временные строки для вашей исходной функции:

def get_next_train(params, get_time_strings):
    ...
    time_strings = get_time_strings(parsed_json)

И назовите это как:

get_next_train(params, time_strings_from_prognosis)

или:

get_next_train(params, time_strings_other)
0 голосов
/ 16 сентября 2018

Общий принцип факторинга заключается в том, чтобы общий код оставался неизменным и превращал различия в параметры функции.

Разница между двумя версиями функции заключается в том, какой подэлемент извлекается при понимании списка. Мы можем абстрагировать разницу в функцию:

def get_next_train(params, select_element):
    res = requests.get(base, params=params)
    parsed_json = res.json()

    # extract times from parsed_json
    time_strings = [select_element(d)
        for d in parsed_json["connections"]]

    ...

Теперь вы можете позвонить

get_next_train(params, lambda d: d["from"]["prognosis"]["departure"])
get_next_train(params, lambda d: d["from"]["departure"])

В качестве альтернативы мы могли бы использовать

    time_strings = [select_element(d["from"])["departure"]
        for d in parsed_json["connections"]]

в функции и

get_next_train(params, lambda x: x["prognosis"])
get_next_train(params, lambda x: x)

в вызове, который устраняет всю избыточность, но намного сложнее понять и обобщить ИМХО.

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