我正在尝试将给定的月份转换为整数格式的月份数。我想尝试转换三种有效格式。以字符串形式给出的月份数字(输入函数返回字符串),月份的缩写和完整的月份名称。
尽管我的功能按预期工作,但我仍然觉得它写得不好,尽管我试图使其尽可能地简洁。特别是,我对刚刚通过的除外声明感到不满意。既要处理字符串转换为整数,又要检查字符串是否是有效月份以转换为整数,这是一项艰巨的任务。
我试图更改try-excepts的顺序,删除了字符串到int以使其位于try-except块上,而没有直接进入异常中的日期格式,但仅此而已。下面的功能是我的最佳尝试。除了创建辅助函数外,我什么都没想到?
def get_start_month_updated():
date_formats = ['%b', '%B']
while True:
month = input("What is the starting month?")
try:
month_num = int(month)
if 1 <= month_num <= 12:
return month_num
except ValueError:
for date_format in date_formats:
try:
month_num = strptime(month, date_format).tm_mon
return month_num
except ValueError:
pass
else:
print("You must enter a valid month")
else:
print("You must enter a valid month")
我的结果是正确的,并且该功能可以按预期工作,但是我觉得代码很混乱,并且有一种更好的方法来完成此操作而不会感到费解。
答案 0 :(得分:1)
首先,您应该创建一个 parse_month 函数以进行更好的测试。 此 parse_month 函数可以具有多个内部解析器,每个内部解析器一种:“ int”,datetime和“%b”,datetime和“%B”。这是实现细节。
做到这一点的一种方法是:
import datetime
import functools
def parse_month(value):
def from_int(v):
month_num = int(v)
if 1 <= month_num <= 12:
return month_num
raise ValueError(v)
def from_month_fmt(fmt, v):
return datetime.datetime.strptime(v, fmt).month
parsers = (
from_int,
functools.partial(from_month_fmt, "%b"),
functools.partial(from_month_fmt, "%B"),
)
for parser in parsers:
try:
return parser(value)
except ValueError:
pass
else:
raise ValueError(value)
然后,您可以使用此功能来提示用户:
def get_start_month_updated():
while True:
month = input("What is the starting month?")
try:
month_num = parse_month(month)
except ValueError:
print("You must enter a valid month")
else:
return month_num
如果您不想重新发明轮子,Arrow是您的朋友:
import arrow
def parse_month(value):
formats = (
"MMMM",
"MMM",
"MM",
"M"
)
for fmt in formats:
try:
return arrow.get(value, fmt).month
except arrow.parser.ParserError:
pass
else:
raise ValueError(value)