[英]Python: Calling a function inside another function with returned values: Error Handling?
I have created the following Python module that converts 24hr time (00:00 to 23:59) into words. 我创建了以下Python模块,该模块将24小时(00:00到23:59)转换为单词。 Function1() tests that the input string matches the correct 24hr format before trying to extract the 12hours, minutes and period (ie am = 'before midday' and pm = 'after midday').
Function1()在尝试提取12小时,分钟和句点之前测试输入的字符串是否与正确的24小时格式匹配(即am =“中午之前”和pm =“中午之后”)。 The following works perfectly as a standalone function, but fails when I call it from function3() when the input string doesn't match the correct format and the try statement doens't execute therefore the return values are not returned.
下面的代码可以完美地用作一个独立的函数,但是当我从function3()调用它时,当输入字符串与正确的格式不匹配并且try语句不执行时,失败,因此不会返回返回值。 Function3() therefore fails as the following return values don't exist.
由于以下返回值不存在,因此Function3()失败。 How do I restructure function1() so that if the pattern doesn't match, the Python module stops running and only executes the else statement in function1() letting the end user know that the input string doesn't match the correct format?
如何重组function1(),以便在模式不匹配时,Python模块停止运行,仅执行function1()中的else语句,让最终用户知道输入字符串与正确的格式不匹配?
"""
Created on 29 May 2017
Convert 24hr format time
into time as words
@author: PeterW
"""
# import site-packages and modules
import re
import time
import argparse
def function1(input_time):
"""convert time from 24hr format
into 12hours, minutes, period"""
period_type = {'AM': 'before midday', 'PM': 'after midday'}
regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
if regexp_object.match(input_time):
try:
time_object = time.strptime(input_time, '%H:%M')
suffix = time.strftime('%p', time_object)
hours = int(time.strftime('%I', time_object))
minutes = time_object[4]
period = period_type.get(suffix)
print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
return hours, minutes, period
except ValueError as err:
print(err)
else:
print("{0} doesn't match required format 00:00 to 23:59"
.format(input_time))
def function2():
"""create dictionary
to lookup equivalent word
of integer number"""
words_lookup = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
11: 'eleven', 12: 'twelve', 13: 'thirteen',
14: 'fourteen', 16: 'sixteen', 17: 'seventeen',
18: 'eighteen', 19: 'nineteen', 20: 'twenty',
21: 'twenty one', 22: 'twenty two', 23: 'twenty three',
24: 'twenty four', 25: 'twenty five', 26: 'twenty six',
27: 'twenty seven', 28: 'twenty eight', 29: 'twenty nine'}
return words_lookup
def function3(input_time):
"""convert 24hr format time
into time as words"""
hours, minutes, period = function1(input_time)
words_lookup = function2()
if hours == 12:
hours2 = words_lookup.get(1)
else:
hours2 = words_lookup.get(hours+1)
if hours == 12 and minutes == 0 and period == 'before midday':
time = 'Midnight'
elif hours == 12 and minutes == 0 and period == 'after midday':
time = 'Midday'
elif minutes == 0:
time = "{0} o'clock {1}.".format(str(words_lookup.get(hours)).title(),
period)
elif minutes == 15:
time = "Quarter past {0} {1}.".format(words_lookup.get(hours),
period)
elif minutes == 30:
time = "Half past {0} {1}.".format(words_lookup.get(hours),
period)
elif minutes == 45:
time = "Quarter to {0} {1}.".format(hours2,
period)
elif minutes < 30:
minutes = str(words_lookup.get(minutes)).capitalize()
time = "{0} minutes past {1} {2}.".format(minutes,
words_lookup.get(hours),
period)
else:
minutes = str(words_lookup.get(60 - minutes)).capitalize()
time = '{0} minutes to {1} {2}.'.format(minutes,
hours2,
period)
print(time)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Convert 24hr format time into time as words")
parser.add_argument('--input_time', metavar='string', required=True,
help='input time in following format 00:00 to 23:59')
args = parser.parse_args()
function3(input_time=args.input_time)
Final version below, thanks for the help. 最终版本如下,感谢您的帮助。
"""
Created on 04 June 2017
Convert 24hr format time
into time as words
@author: PeterW
"""
# import site-packages and modules
import sys
import re
import time
import argparse
def validate_time_format(input_time):
"""Validate that input string
matches require 24hr time format"""
regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
if regexp_object.match(input_time):
print("Processing: {0} into words".format(input_time))
time_str = input_time
else:
print("{0} doesn't match required input format: 00:00 to 23:59".format(input_time))
sys.exit()
return time_str
def extract_time(time_str):
"""convert time from 24hr format
into 12hours, minutes, period"""
period_type = {'AM': 'before midday', 'PM': 'after midday'}
try:
time_object = time.strptime(time_str, '%H:%M')
suffix = time.strftime('%p', time_object)
hours = int(time.strftime('%I', time_object))
minutes = time_object[4]
period = period_type.get(suffix)
# print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
return hours, minutes, period
except ValueError as err:
print(err)
def time_lookup():
"""create dictionary
to lookup equivalent word
of integer number"""
words_lookup = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',
6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten',
11: 'eleven', 12: 'twelve', 13: 'thirteen',
14: 'fourteen', 16: 'sixteen', 17: 'seventeen',
18: 'eighteen', 19: 'nineteen', 20: 'twenty',
21: 'twenty one', 22: 'twenty two', 23: 'twenty three',
24: 'twenty four', 25: 'twenty five', 26: 'twenty six',
27: 'twenty seven', 28: 'twenty eight', 29: 'twenty nine'}
return words_lookup
def time_as_words(input_time):
"""convert 24hr format time
into time as words"""
time_str = validate_time_format(input_time)
hours, minutes, period = extract_time(time_str)
words_lookup = time_lookup()
if hours == 12:
hours2 = words_lookup.get(1)
else:
hours2 = words_lookup.get(hours+1)
if hours == 12 and minutes == 0 and period == 'before midday':
time = 'Midnight'
elif hours == 12 and minutes == 0 and period == 'after midday':
time = 'Midday'
elif minutes == 0:
time = "{0} o'clock {1}.".format(str(words_lookup.get(hours)).title(),
period)
elif minutes == 15:
time = "Quarter past {0} {1}.".format(words_lookup.get(hours),
period)
elif minutes == 30:
time = "Half past {0} {1}.".format(words_lookup.get(hours),
period)
elif minutes == 45:
time = "Quarter to {0} {1}.".format(hours2,
period)
elif minutes < 30:
min_str = str(words_lookup.get(minutes)).capitalize()
time = "{0} minute{1} past {2} {3}.".format(min_str,
"" if minutes == 1 else "s",
words_lookup.get(hours),
period)
else:
min_str = str(words_lookup.get(60 - minutes)).capitalize()
time = '{0} minute{1} to {2} {3}.'.format(min_str,
"" if 60 - minutes == 1 else "s",
hours2,
period)
print(time)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Convert 24hr format time into time as words")
parser.add_argument("-t", "--input_time", metavar="time", type=str, required=True,
help='input time in the following format 00:00 to 23:59')
args = parser.parse_args()
time_as_words(input_time=args.input_time)
When your function1
fails, it implicitly returns a None
. 当
function1
失败时,它隐式返回None
。 The caller has to be aware of this possibility: 呼叫者必须意识到这种可能性:
retval = function1(input_time)
if retval is None:
# do something - say, exit
else:
hours, minutes, period = retval
Switch the if regexp_object.match(input_time)
for an if not regexp_object.match(input_time)
, and switch the logic around too: 将
if regexp_object.match(input_time)
切换为if not regexp_object.match(input_time)
,并同时切换逻辑:
def function1(input_time):
"""convert time from 24hr format
into 12hours, minutes, period"""
period_type = {'AM': 'before midday', 'PM': 'after midday'}
regexp_object = re.compile(r'^(([01]\d|2[0-3]):([0-5]\d)|23:59)$')
# Switch to checking if it isn't valid instead, and exit early if that's the case
if not regexp_object.match(input_time):
print("{0} doesn't match required format 00:00 to 23:59"
.format(input_time))
exit(-1)
# Since we already returned if the regex didn't match, we know if it reaches this point it'll match
try:
time_object = time.strptime(input_time, '%H:%M')
suffix = time.strftime('%p', time_object)
hours = int(time.strftime('%I', time_object))
minutes = time_object[4]
period = period_type.get(suffix)
print("{0}:{1} {2}".format(hours, str(minutes).zfill(2), period))
return hours, minutes, period
except ValueError as err:
print(err)
Note that exit
actually exits the program altogether. 请注意,
exit
实际上是完全退出程序。 If you merely wanted to return something (such as None
, to sign that something went wrong) to a further function, you could instead do return None
and the function would return then and there. 如果您只想将某个内容(例如
None
,以表示出现问题)返回到另一个函数,则可以改return None
然后该函数将在那儿返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.