编写和使用自己的函数-基础知识

4
你的任务是编写和测试一个函数,该函数接受两个参数(年份和月份),并返回给定月份/年份组合的天数(是的,我们知道只有二月份会受到年份值的影响,但我们希望函数是通用的)。现在,请确保函数在其参数不合理的情况下返回None。
使用填充了月份长度的列表。你可以在函数内部创建它 - 这个技巧将显著缩短代码。
我已经写出了代码,但不确定如何添加'none'的部分。能有人帮我吗?
def IsYearLeap(year):
    if (year%4==0):
        return True
    if (year%4!=0):
        return False

def DaysInMonth(year,month):
    if month in {1, 3, 5, 7, 8, 10, 12}:
        return 31

    elif month==2:
        if IsYearLeap(year):
            return 29
        else:
            return 28
    elif month in {4,6,8,9,11}:
        return 30
    else:
        return none

 testyears = [1900, 2000, 2016, 1987,2019]
 testmonths = [ 2, 2, 1, 11,4]
 testresults = [28, 29, 31, 30,33]
 for i in range(len(testyears)):
    yr = testyears[i]
    mo = testmonths[i]
    print(yr,mo,"->",end="")
    result = DaysInMonth(yr,mo)
    if result == testresults[i]:
        print("OK")
    else:
        print("Failed")

3
Python是大小写敏感的,因此必须使用None - Michael Butscher
我们不喜欢做作业。此外,这个问题没有展示出任何研究努力。 - MilkyWay90
1
@MilkyWay90,代码已经接近完成,问题只涉及一个小问题,对于初学者来说很容易忽略。在我看来,这完全是相关主题。 - Michael Butscher
@MichaelButscher 我明白了,我已经改变了我的投票。 - MilkyWay90
7个回答

0

看起来你犯了一个简单的错误。如果你不习惯大小写敏感的编程语言或者没有编程语言的经验,这是可以理解的。

关键字None被拼错成了未定义的单词none


0

我认为你的测试结果是错误的。1900年的2月份应该有29天,2019年4月份应该有30天。另外,应该是None而不是none。还有一个问题是最好使用月份列表,这样你可以使用[1, 3, 5, 7, ...]而不是{1, 3, 5, 7, ...}。

此外,从你的测试用例中,你不会得到None,如果你想检查这种情况,你可以检查月份=13,这样你就可以覆盖这种情况了。


0

作为对这个问题其他好答案的进一步评论,闰年的正确规则应该是:

def is_leap_year(year):
    """ is it a leap year?
    >>> is_leap_year(1984)
    True

    >>> is_leap_year(1985)
    False

    >>> is_leap_year(1900)
    False

    >>> is_leap_year(2000)
    True
    """
    return (year % 4 == 0 and 
            (year % 100 != 0 or year % 400 == 0))

同样地,测试用例需要明确指出1900年不是闰年,而2000年是。我建议为is_leap_year编写一组单独的测试用例。最终,在生产代码中,最好使用众多时间/日期库之一。我提供的注释利用doctest快速提供了这个单元测试。

0
一个没有显式使用return语句的函数会隐式地返回None
除了拼写错误(noneNone),你在这里无意中使用了它:
def IsYearLeap(year):
    if (year%4==0):
        return True
    if (year%4!=0):
        return False

你能看到如果两个条件都不成立会发生什么吗?它既不会 返回 False 也不会 True,这可能是调用者期望的。 (虽然如果您检查 None == True,您将得到False,并且not NoneTrue,因此您不会收到语法错误,只会得到一个结果,这可能与您的预期不同-最糟糕的错误!)


0

几个小细节:

  • 您应该删除重复的第8个月(八月列出了30和31天),
  • 最好用列表[]替换括号{},
  • 将none替换为None(Python区分大小写,None是关键字),
  • 增加一个闰年的条件:

(year % 400 == 0) and (year % 100 == 0) -> 返回True

(year % 4 == 0) and (year % 100 != 0) -> 返回True


0
def is_year_leap(year):
    return year % 4 == 0 and year % 100 != 0 or year % 400 == 0


def days_in_month(year, month):
    days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    if type(year) != int or year < 1582 or\
    type(month) != int or month < 1 or month > 12:
        return None
    elif is_year_leap(year):
        del days[1]
        days.insert(1, 29)
    return days[month - 1]


test_years = [1900, 2000, 2016, 1987]
test_months = [2, 2, 1, 11]
test_results = [28, 29, 31, 30]
for i in range(len(test_years)):
    yr = test_years[i]
    mo = test_months[i]
    print(yr, mo, "->", end="")
    result = days_in_month(yr, mo)
    if result == test_results[i]:
        print("OK")
    else:
        print("Failed")

0
def IsYearLeap(year):
    return year % 4 == 0 & (year % 400 == 0 | year % 100 != 0)
def DaysInMonth(year,month):
     if month in [1, 3, 5, 7, 8, 10, 12]:
        return 31
     elif month==2:
        if IsYearLeap(year):
            return 29
        else:
            return 28
     elif month in [4,6,8,9,11]:
        return 30
     else:
        return None
#

testYears = [1900, 2000, 2016, 1987]
testMonths = [2, 2, 1, 11]
testResults = [28, 29, 31, 30]
for i in range(len(testYears)):
    yr = testYears[i]
    mo = testMonths[i]
    print(yr, mo, "->", end="")
    result = DaysInMonth(yr, mo)
    if result == testResults[i]:
        print("OK")
    else:
        print("Failed")

1
有几件事情需要注意:您使用二进制运算符而不是逻辑运算符(请使用and/or代替&/|)。for i in range(len...)是不好的编程风格,请改用for yr, mo in zip(testYears, testMonths)。最后,请尽量使用pep-8风格的变量。另外,如果您在回答问题,请添加一些注释以说明原始解决方案失败的原因。 - MrBean Bremen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接