Python:使用返回值在另一个函数中调用一个函数:错误处理?

Python: Calling a function inside another function with returned values: Error Handling?

我创建了以下 Python 模块,可将 24 小时制(00:00 到 23:59)转换为文字。 Function1() 在尝试提取 12 小时、分钟和期间(即 am = 'before midday' 和 pm = 'after midday')之前测试输入字符串是否匹配正确的 24 小时格式。以下作为独立函数完美运行,但是当我从 function3() 调用它时失败,当输入字符串与正确的格式不匹配并且 try 语句不执行因此 return 值不是 return编辑。 Function3() 因此失败,因为以下 return 值不存在。我如何重组 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)

下面是最终版本,感谢您的帮助。

"""
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)

当您的 function1 失败时,它隐式 returns 一个 None。调用者必须意识到这种可能性:

retval = function1(input_time)
if retval is None:
    # do something - say, exit
else:
    hours, minutes, period = retval

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)

请注意 exit 实际上完全退出了程序。如果你只是想 return 一些东西(比如 None,表示出了问题)到另一个函数,你可以改为 return None 并且函数会 return然后那里。