问题描述
我有一个名为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'未定义。
我当然可以复制粘贴整个代码并更改我需要的位,但有没有更好的方法呢?
1楼
因子分解的一般原则是保持公共代码相同并将差异转化为函数参数。
函数的两个版本之间的区别在于列表推导中提取了哪个子元素。 我们可以将差异抽象为函数:
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)
在通话中,它消除了所有冗余,但更难以理解和推广恕我直言。
2楼
封装保持不变的内容。 封装各种不同的东西。
您可以定义两个不同的函数来获取时间字符串。 一个得到预后:
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)
3楼
您可以在调用函数时尝试添加第二个参数:
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'参数只是一个布尔值,但它可以是你想要的任何东西......