【问题标题】:Python: Calling a function inside another function with returned values: Error Handling?Python:在另一个函数中调用一个函数并返回值:错误处理?
【发布时间】:2017-06-03 20:46:53
【问题描述】:

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

【问题讨论】:

    标签: python return-value nested-function


    【解决方案1】:

    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 实际上完全退出了程序。如果您只是想将某些内容(例如 None,以表示出现问题)返回到另一个函数,则可以改为执行 return None,然后该函数将在那里返回。

    【讨论】:

    • 嗨佩德罗,感谢以下。我正在考虑将正则表达式移动到一个单独的函数中,该函数将被调用以验证输入字符串,如果它不正确,将请求一个与正确格式匹配的新输入字符串,然后继续提取 12 小时、分钟和期间。这样,如果输入字符串不正确,至少程序不会终止或失败。
    • @PeterWilson 是的,这也是可能的。代替exit,调用on_failure 或其他函数。
    • 感谢佩德罗的帮助。一旦找到向用户请求新输入的最佳方式,我将更新我的结果。
    【解决方案2】:

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

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

    【讨论】:

    • 如何在不退出函数的情况下使用以下命令请求新的输入字符串。
    • 我不明白你的要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-04
    • 2013-03-18
    • 2020-03-27
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多