【问题标题】:Beginning date is bigger than the end date of a calendaristic period开始日期大于日历周期的结束日期
【发布时间】:2021-10-17 12:20:47
【问题描述】:

我正在尝试编写一个函数来验证包含 2 个日期(开始和结束)、目的地和价格的包裹

最初,我尝试编写一个函数来“创建”日期并将它们放在一个列表中,然后比较它们以确定结束日期是否低于开始日期,但我认为这太复杂了,所以我求助于datetime 内置模块

但是,当我尝试运行测试功能时,它会失败并输出此错误消息

File "C:\Users\Anon\Desktop\Fac\FP\pythonProject\main.py", line 65, in valideaza_pachet
    raise Exception(err)
Exception: wrong dates!

我认为我一定搞砸了 valideaza_pachet() 函数中的一个条件,但我不明白我做错了什么

代码:

import time
import calendar
from datetime import date, datetime


def creeaza_pachet(data_i, data_s, dest, pret):
    # function that creates a tourism package, data_i = beginning date, data_s = end date, dest = destination and pret = price
    return {
        "data_i": data_i,
        "data_s": data_s,
        "dest": dest,
        "pret": pret
    }


def get_data_i(pachet):
    # functie that returns the beginning date of the package
    return pachet["data_i"]


def get_data_s(pachet):
    # functie that returns the end date of the package
    return pachet["data_s"]


def get_destinatie(pachet):
    # functie that returns the destination of the package
    return pachet["dest"]


def get_pret(pachet):
    # functie that returns the price of the package
    # input: pachet - un pachet
    # output: pretul float > 0 al pachetului
    return pachet["pret"]


def valideaza_pachet(pachet):
    #functie that validates if a package was correctly introduced or not
    #it raises an Exception as ex if any of the conditions aren't met
    err = ""
    if get_data_i(pachet) < get_data_s(pachet):
        err += "wrong dates!" # if the end date is lower than the beginning date
    if get_destinatie(pachet) == " ":
        err += "wrong destination!"
    if get_pret(pachet) <= 0:
        err += "wrong price!"
    if len(err) > 0:
        raise Exception(err)


def test_valideaza_pachet():
    pachet = creeaza_pachet(datetime.strptime('24/08/2021',"%d/%m/%Y"), datetime.strptime('26/08/2021',"%d/%m/%Y"), "Galati", 9000.1)
    valideaza_pachet(pachet)
    pachet_gresit = creeaza_pachet(datetime.strptime('24/08/2021',"%d/%m/%Y"), datetime.strptime('22/08/2021',"%d/%m/%Y"), "Galati", 9000.1)
    try:
        valideaza_pachet(pachet_gresit)
        assert False
    except Exception as ex:
        assert (str(ex) == "wrong dates!\n")
    alt_pachet = creeaza_pachet(datetime.strptime('24/08/2021',"%d/%m/%Y"), datetime.strptime('22/08/2021',"%d/%m/%Y"), " ", -904)
    try:
        valideaza_pachet(alt_pachet)
        assert False
    except Exception as ex:
        assert(str(ex) == "wrong dates!\nwrong destination!\nwrong price!\n")


def test_creeaza_pachet():
    data_i_string = '24/08/2021'
    data_i = datetime.strptime(data_i_string, "%d/%m/%Y")
    data_s_string = '26/08/2021'
    data_s = datetime.strptime(data_s_string, "%d/%m/%Y")
    dest = "Galati"
    pret = 9000.1
    pachet = creeaza_pachet(data_i,data_s,dest,pret)
    assert (get_data_i(pachet) == data_i)
    assert (get_data_s(pachet) == data_s)
    assert (get_destinatie(pachet) == dest)
    assert (abs(get_pret(pachet) - pret) < 0.0001)


def run_teste():
    test_creeaza_pachet()
    test_valideaza_pachet()


def run():
    pass


def main():
    run()
    run_teste()


main()

【问题讨论】:

  • 您希望 assert False 做什么?此外,对于这样的事情,您会发现 Python 类非常有用
  • 当我写它时,我的想法是,如果我使用 valideaza_pachet() 函数检查 pachet_gresit 它将是 False,因为我将 pachet_gresit 写为错误的包,即结束日期低于开始日期
  • assert False 会引发异常,您会捕获并报告“错误日期”
  • 没有阅读您的编辑,至于类,我们还不允许使用它们(这是一个 uni 项目,如果它看起来不像哈哈)
  • 后续验证是个坏主意。检查 creeaza_pachet 中的日期,如果顺序错误,则引发异常

标签: python date dictionary datetime error-handling


【解决方案1】:

这更像是一次代码审查,有点离题,但是……首先,

  • 删除所有assert False - 这些不会有任何用处
  • 删除 getter 函数,这只会让事情变得复杂(只要您不使用自定义类,只需在代码中使用 dict[key]
  • 删除不必要的导入,例如calendar
  • 您可能还想删除 runmain 函数(再次令人费解) - 只需调用您需要的函数

然后您可以更改valideaza_pachet 以引发特定值错误:

def valideaza_pachet(pachet):
    if pachet["data_i"] >= pachet["data_s"]:
        raise ValueError("start date must be < end date")
    if pachet["dest"] == " ":
        raise ValueError("destination must not be empty")
    if pachet["pret"] <= 0:
        raise ValueError("price must be >= 0")
    # returns None if no exception was raised

现在要测试一个有效的包,你只需这样做

valideaza_pachet(pachet) # no exception expected

如果没有可以进行单元测试的类,测试无效包会稍微复杂一些(参见例如here) - 但您可以捕获异常并使用 try/except 的 else 子句引发 AssertionError说你想要一个例外:

try:
    valideaza_pachet(pachet_gresit)
except Exception as ex:
    print(f"successfully received exception: {ex}")
else:
    raise AssertionError("validation should have raised an Exception")

甚至

assert str(ex) == "start date must be < end date", f"got '{ex}', expected 'start date must be < end date'"

代替print 声明。

【讨论】:

  • 感谢您的提示,实际上并不知道您可以调用 dict[key] 而不是编写 get_ 函数,我们的讲师只向我们展示了后一种方式:/ 至于课程,我说了两次我不能使用它们,但无论如何我都会对它们进行更多研究
  • @manowar447233 不用担心,该应用程序非常适合class ^^ 也许讲师正在为此做准备。希望我能给你一些见解。顺便提一句。字典也有一个 get 方法,如果你不知道你想要的密钥是否在那里,它会很有帮助 - 如果没有,它不会引发 KeyError 而是返回一个默认值。
猜你喜欢
  • 2016-06-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
相关资源
最近更新 更多