Article Outline

# 测试驱动的开发

In mathematics and computer science, an algorithm is an unambiguous specification of how to solve a class of problems. Algorithms can perform calculation, data processing, and automated reasoning tasks.

“算法”，其实没多神秘，就是 “解决问题的步骤” 而已。

• 年份应该是 4 的倍数；
• 年份能被 100 整除但不能被 400 整除的，不是闰年。
• 所以，相当于要在能被 4 整除的年份中，排除那些能被 100 整除却不能被 400 整除的年份。

``````def is_leap(year):
# 请在这里写下你的代码。
pass``````

• `is_leap(4)` 的返回值应该是 `True`
• `is_leap(200)` 的返回值应该是 `False`
• `is_leap(220)` 的返回值应该是 `True`
• `is_leap(400)` 的返回值应该是 `True`

``````def is_leap(year):
# 请在这里写下你的代码。
pass

print(is_leap(4) is True)
print(is_leap(200) is False)
print(is_leap(220) is True)
print(is_leap(400) is True)``````
``````False
False
False
False``````

• 先假定都不是闰年；
• 再看看是否能被 `4` 整除；
• 再剔除那些能被 `100` 整除但不能被 `400` 整除的年份……

``````def is_leap(year):
r = False
return r

print(is_leap(4) is True)
print(is_leap(200) is False)
print(is_leap(220) is True)
print(is_leap(400) is True)``````
``````False
True
False
False``````

``````def is_leap(year):
r = False
if year % 4 == 0:
r = True
return r

print(is_leap(4) is True)
print(is_leap(200) is False)
print(is_leap(220) is True)
print(is_leap(400) is True)``````
``````True
False
True
True``````

• 因为它能被 `4` 整除，所以，使 `r = True`
• 然后再看它是否能被 `100` 整除 —— 能 —— 既然如此再看它能不能被 `400` 整除，
• 如果不能，那就让 `r = False`
• 如果能，就保留 `r` 的值…… 如此这般，`200` 肯定使得 `r = False`
``````def is_leap(year):
r = False
if year % 4 == 0:
r = True
if year % 100 == 0:
if year % 400 !=0:
r = False
return r

print(is_leap(4) is True)
print(is_leap(200) is False)
print(is_leap(220) is True)
print(is_leap(400) is True)``````
``````True
True
True
True``````

``````# cpython/Lib/datetime.py
def _is_leap(year):
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
print(_is_leap(300))``````
``False``

• 语法错误（Syntax Errors）
• 意外（Exceptions）

``print(11/0)``
``````---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

<ipython-input-2-5544d98276be> in <module>
----> 1 print(11/0)

ZeroDivisionError: division by zero``````

``````BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
|    +-- FloatingPointError
|    +-- OverflowError
|    +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
|    +-- ModuleNotFoundError
+-- LookupError
|    +-- IndexError
|    +-- KeyError
+-- MemoryError
+-- NameError
|    +-- UnboundLocalError
+-- OSError
|    +-- BlockingIOError
|    +-- ChildProcessError
|    +-- ConnectionError
|    |    +-- BrokenPipeError
|    |    +-- ConnectionAbortedError
|    |    +-- ConnectionRefusedError
|    |    +-- ConnectionResetError
|    +-- FileExistsError
|    +-- FileNotFoundError
|    +-- InterruptedError
|    +-- PermissionError
|    +-- ProcessLookupError
|    +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
|    +-- NotImplementedError
|    +-- RecursionError
+-- SyntaxError
|    +-- IndentationError
|         +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
|    +-- UnicodeError
|         +-- UnicodeDecodeError
|         +-- UnicodeEncodeError
|         +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning``````

`FileNotFoundError` 为例 —— 当我们想要打开一个文件之前，其实应该有个办法提前验证一下那个文件是否存在。如果那个文件并不存在，就会引发 “意外”。

``f = open('test_file.txt', 'r')``
``````---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-3-5fac19176fe6> in <module>
----> 1 f = open('test_file.txt', 'r')

FileNotFoundError: [Errno 2] No such file or directory: 'test_file.txt'``````

``````try:
f = open('test_file.txt', 'r')
except FileNotFoundError as fnf_error:
print(fnf_error)``````
``[Errno 2] No such file or directory: 'test_file.txt'``

``````try:
do_something()
except built_in_error as name_of_error:
do_something()
else:
do_something()``````

``````try:
do_something()
except built_in_error as name_of_error:
do_something()
else:
do_something()
finally:
do_something()``````

``````try:
do_something()
except built_in_error as name_of_error:
do_something()
else:
try:
do_something()
except built_in_error as name_of_error:
do_something()
...``````