若是没有看基础部分第一章,请前往Python基础知识两部曲:一java
1. 无参数的函数: def greet_user(): """显示简单的函数体""" print("Hello Python") greet_user() 获得: Hello Python 2. 有参数的函数: def greet_user(username): """显示简单的函数体""" print("Hello Python: "+username) greet_user('kobe') 获得: Hello Python: kobe
在函数greet_user()中,变量username是一个形参---函数完成其工做所须要的一项信息.在代码greet_user('kobe')中,值'kobe'是一个实参。python
须要注意参数的位置程序员
def describe_pet(animal_type,pet_name): print("\nI have a " + animal_type + ".") print("My "+ animal_type + "'s name is "+pet_name.title()+".") describe_pet('dog','james') describe_pet('dog','iverson') 获得: I have a dog. My dog's name is James. I have a dog. My dog's name is Iverson.
关键字实参是传递给函数的名称-值对,直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。与参数顺序无关。json
def describe_pet(animal_type,pet_name): print("\nI have a " + animal_type + ".") print("My "+ animal_type + "'s name is "+pet_name.title()+".") describe_pet(pet_name = 'kkkk',animal_type = 'cat') 获得: I have a cat. My cat's name is Kkkk.
编写函数能够给每一个形参指定默认值,app
# 注意已经设置了默认值的参数要放在后面, def describe_pet2(pet_name,animal_type = 'dog'): print("\nI have a " + animal_type + ".") print("My "+ animal_type + "'s name is "+pet_name.title()+".") describe_pet2('kobe') describe_pet2(pet_name = 'james') 获得: I have a dog. My dog's name is Kobe. I have a dog. My dog's name is James.
调用返回值的函数时,须要提供一个变量,用于存储返回的值。dom
def get_formatted_name(first_name,last_name): """返回整洁的姓名""" full_name = first_name + '-' +last_name return full_name.title() musician = get_formatted_name('kobe','bryant') print(musician) 获得: Kobe-Bryant
def get_formatted_name(first_name,last_name,middle_name= ''): """返回整洁的姓名""" if middle_name: full_name = first_name +'-'+middle_name+'-'+last_name else: full_name = first_name + '-' +last_name return full_name.title() musician = get_formatted_name('kobe','bryant') print(musician) musician = get_formatted_name('kobe','bryant','vboy') print(musician) 获得: Kobe-Bryant Kobe-Vboy-Bryant
def build_person(first_name,last_name,age = ''): """返回一个字典,其中包含有关一我的的信息""" person = {'first':first_name,'last':last_name} if age: person['age'] = age pass return person musician = build_person('kobe','bryant',23) print(musician) 获得: {'age': 23, 'last': 'bryant', 'first': 'kobe'}
ef get_formatted_name(first_name,last_name,middle_name= ''): """返回整洁的姓名""" if middle_name: full_name = first_name +'-'+middle_name+'-'+last_name else: full_name = first_name + '-' +last_name return full_name.title() while True: print("\nPlease tell me you name:") first_name = input("first Name: ") last_name = input("last Name: ") formatted_name = get_formatted_name(first_name,last_name) print(formatted_name) msg = input("do you want to exit (Y/N)") if msg.upper() == 'Y': break 终端运行获得: liukingdeMacBook-Pro:desktop liuking$ python3 input.py Please tell me you name: first Name: kobe last Name: bryant Kobe-Bryant do you want to exit (Y/N)n Please tell me you name: first Name: chris last Name: paul Chris-Paul do you want to exit (Y/N)y liukingdeMacBook-Pro:desktop liuking$
# 没有使用函数是这样的。 """将未确认的用户,进行认证。""" unconfirmed_users = ['one','two','three'] confirmed_users = [] while unconfirmed_users: """处理用户认证操做""" current_user = unconfirmed_users.pop() print("verifying User:"+current_user) confirmed_users.append(current_user) """打印认证用户""" print("\nThe following users have been confirmed: ") for user in confirmed_users: print(user.title()) 获得: verifying User:three verifying User:two verifying User:one The following users have been confirmed: Three Two One
unconfirmed_users = ['first','second','third'] confirmed_users = [] """处理用户认证操做""" def deal_verify_user(unconfirmed_users,confirmed_users): while unconfirmed_users: """处理用户认证操做""" current_user = unconfirmed_users.pop() print("verifying User:"+current_user) confirmed_users.append(current_user) def print_verify_user(confirmed_users): for user in confirmed_users: print(user.title()) deal_verify_user(unconfirmed_users,confirmed_users) print("\nThe following users have been confirmed: ") print_verify_user(confirmed_users) 获得: verifying User:third verifying User:second verifying User:first The following users have been confirmed: Third Second First
上面咱们发现获得同样的结果,但使用了函数处理能够作到复用,且逻辑比较清晰,易于扩展。ide
若是咱们像备份以前的数据,咱们就不能修改未认证的用户,这个时候咱们能够用切片来处理咱们的操做了。函数
unconfirmed_users = ['first','second','third'] confirmed_users = [] """处理用户认证操做""" def deal_verify_user(unconfirmed_users,confirmed_users): while unconfirmed_users: """处理用户认证操做""" current_user = unconfirmed_users.pop() print("verifying User:"+current_user) confirmed_users.append(current_user) def print_user(confirmed_users): for user in confirmed_users: print(user.title()) """这里咱们将列表的副本传给函数,列表的原始数据不会被修改""" deal_verify_user(unconfirmed_users[:],confirmed_users) print("\nThe following users have been confirmed: ") print_user(confirmed_users) print("\n展现原始数据: ") print_user(unconfirmed_users) 获得: verifying User:third verifying User:second verifying User:first The following users have been confirmed: Third Second First 展现原始数据: First Second Third
有的时候咱们不知道函数须要接受多少个实参,python容许函数从调用语句中收集任意数量的实参。工具
“”“这里*toppons指定了一个空元组,将收到的全部值都封装在这个这元组中。”“” def make_pizza(*toppons): """打印顾客点的全部配料""" print("\nMaking a pizza with the following toppings") for top in toppons: print("- "+top.title()) make_pizza('pepperoni') make_pizza('pepperoni','green peppers','extra cheese') 获得: Making a pizza with the following toppings - Pepperoni Making a pizza with the following toppings - Pepperoni - Green Peppers - Extra Cheese
若是要让函数接受不一样类型的实参,必须在函数定义中接纳任意数量实参的形参放在最后。python先匹配位置实参和关键字实参,再匹配任意实参,*因此这里咱们把make_pizza(size,toppons),位置实参在前,任意实参在后。**单元测试
def make_pizza(size,*toppons): """打印顾客点的全部配料""" print("\nMaking a " + str(size) +"-inch pizza with the following toppings") for top in toppons: print("- "+top.title()) make_pizza(18,'pepperoni') make_pizza(33,'pepperoni','green peppers','extra cheese') 获得: Making a 18-inch pizza with the following toppings - Pepperoni Making a 33-inch pizza with the following toppings - Pepperoni - Green Peppers - Extra Cheese
有时候须要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种状况下,可将函数编写成可以接受任意数量键值对---调用语句提供了多少就接爱多少。
def build_profile(first,last,**user_info): """建立一个字典""" profile = {} profile['first_name'] = first profile['last_name'] = last for key,value in user_info.items(): profile[key] = value return profile info = build_profile('Kobe','bryant',like = 'ball',age = 35) print(info) 获得: {'first_name': 'Kobe', 'last_name': 'bryant', 'age': 35, 'like': 'ball'}
函数的优势之一是,使用它们可将代码块与主程序分离,经过给函数指定描述性名称,可以让主程序容易得多。还能够更进一步,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。import语句容许在当前运行的程序文件中使用模块代码。
经过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点入在程序的高层逻辑上,还能让你在众多不一样的程序中重用函数。将函数存储在独立文件后,可与其它程序员共享这些文件而不是整个程序。知道如何导入函数,还能让你使用其它程序员编写的函数库。
使用import语句导入了名为module_name.py的整个模块,就可以使用下面的语法来使用其中任何一个函数。
module_name.function_name()<br/>
下面咱们建立一个input.py文件。
def make_pizza(size,*toppons): """打印顾客点的全部配料""" print("\nMaking a " + str(size) +"-inch pizza with the following toppings") for top in toppons: print("- "+top.title())
再建立一个test_input.py文件
import input input.make_pizza(18,'pepperoni') input.make_pizza(33,'pepperoni','green peppers','extra cheese') 获得: Making a 18-inch pizza with the following toppings - Pepperoni Making a 33-inch pizza with the following toppings - Pepperoni - Green Peppers - Extra Cheese
上面咱们使用import 导入input文件。而后使用文件名input,再调用函数。
#####2.导入特定的函数。
还能够导入模块中特写的函数,这种导入方法的语法以下:from module_name import function_name
from module_name import function_0,function_1,function_2
对于只想导入要使用的函数,代码将相似于下面这样:
使用这种语法,调用函数时就无需使用句点,因为咱们在import语句中显示地导入了函数make_pizza,所以调用它时只须要指定其名称。
from input import make_pizza make_pizza(18,'pepperoni') make_pizza(33,'pepperoni','green peppers','extra cheese') 能够获得一样的效果。
有的时候要导入的函数名称可能与程序中现有的名称冲突,或者函数名称太长,可指定简短而独一无二的别名---函数的另外一个名称,相似于外号。
指定别名的通用语法是:from module_name import function_name as fn
下面咱们能够把上面代码修改一下:
from input import make_pizza as mp mp(18,'pepperoni') mp(33,'pepperoni','green peppers','extra cheese')
还能够给模块指定别名。给模块指定别名通用语法以下:<br/>import module_name as mn<br/>
代码以下:
import input as put put.make_pizza(18,'pepperoni') put.make_pizza(33,'pepperoni','green peppers','extra cheese')
使用星号() 运算符可让Python导入模块中全部的函数:
`from module_name import `
首先建立有两个函数的文件:
def make_pizza(size,*toppons): """打印顾客点的全部配料""" print("\nMaking a " + str(size) +"-inch pizza with the following toppings") for top in toppons: print("- "+top.title()) def make_KFC(size,*toppons): """打印顾客点的全部配料""" print("\nMaking a " + str(size) +"-inch KFC with the following toppings") for top in toppons: print("- "+top.title())
再调用:
from input import * make_pizza(33,'pepperoni','green peppers','extra cheese') make_KFC(33,'pepperoni','green peppers','extra cheese') 获得: Making a 33-inch pizza with the following toppings - Pepperoni - Green Peppers - Extra Cheese Making a 33-inch KFC with the following toppings - Pepperoni - Green Peppers - Extra Cheese
注意:import语句中星号让Python将模块中每一个函数都复制到这个程序文件中,因为导入了每一个函数,可经过名称来调用每一个函数,而无需使用句点表示法。但使用并不是本身编写的大型模块时,最好不要采用这种导入方法:若是模块中有函数的名称与你项目的中使用的名称相同,可能致使意想不到的结果:Python可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入全部的函数。
最佳作法:要么只导入你须要使用的函数,要么导入整个模块并使用句点表示法。这能让代码更清晰,更容易理解和阅读。
编写函数时,须要牢记几个细节:应给函数指定描述性名称,且只在其中使用小写字母和下划线,描述性名称可帮助你和别人明白代码想要什么,给模块命名时也应按上述约定。
给形参指定默认值时,等号两边不要有空格。
def function_name(parameter_0,parameter_1='devault value')
对于函数调用中的关键字实参,
function_name(value_0,parameter='value')
完
全部的面向对象编辑思想都是同样的,因此这一篇对因而程序员的你必定是很是简单的.
class Car(): """一次模拟汽车的简单尝试""" def __init__(self, make, model, year): self.make = make self.model = model self.year = year self.odometer_reading = 0 def get_descriptive_name(self): long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() def update_odometer(self, mileage): if mileage >= self.odometer_reading: self.odometer_reading = mileage else: print("you can't roll back an odometer!")
这里面我就建立了一个一个Car类,不要问我为何这么写,这就是约定。
代码说明def __init__(self, make, model, year):
- 这是一个特殊的函数,使用两个下划线标记主要是为了跟其它的普通函数区分开来。 在java里这个叫构造函数
- 里面有带了几个参数来填充属性,还能够添加默认参数,里面我添加了一个odometer_reading这个属性
- 这里面我添加了两个方法get_descriptive_name 和 update_odometer 这里面必须传入self,这是对自身的一种引用,另外还能够在后面添加若干参数。
使用类:
byd = Car('byd','byd tang','2017') #实例化Car类 str1 = byd.get_descriptive_name() # 调用类的方法 print(str1.title()) 获得结果 2017 Byd Byd Tang 再调用一个带参数的方法 byd.update_odometer(100); print('move '+str(byd.odometer_reading)+' miles') 获得结果: move 100 miles
直接在Car这个文件里再写一个子类,电动车类:
class ElectriCar(Car): #继承Car类 """电动汽车独特之处""" def __init__(self, make, model, year, battery_size=100): """初始化父类的属性""" super().__init__(make, model, year) #这里继承父类的属性 和java里的super方法同样 self.battery_size = battery_size # 子类有本身的属性 def descript_batter(self): print("This car has a " + str(self.battery_size) + " kwh battery.") def fill_gas_tank(self): print("i hava a battery") my_tesla = ElectriCar('tesla', 'model s', '2016') print(my_tesla.get_descriptive_name()) #引用父类的描述方法 print(my_tesla.fill_gas_tank()) #重写子类的电池方法 获得结果: 2016 Tesla Model S i hava a battery
代码说明
####9.3 导入类
####9.4 Python标准库
异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操做,同时告诉Python发生异常时怎么办。使用了try-except代码块时,即使出现异常,程序也将继续运行:显示你编写的友好的错误信息,而不是令用户迷惑的traceback.
print(5/0)
当你认为可能发生了错误时,可编写一个try-except代码块来处理可能引起的异常。
处理ZeroDivisionError异常的try-except代码块相似于下面这样:
try: print(5/0) except Exception, e: print("You can't divide by zero!")
若是程序出现异常,就执行print("You can't divide by zero!"),再也不是traceback:
发生错误时,若是程序还有工做没有完成,妥善处理错误就尤为重要。这种状况常常会现出如今要求用户提供输入的程序中;若是程序可以妥善地处理无效输入,就能再提示用户提供有效输入,而不至于崩溃。
下面来一个只执行除法的简单计算器:
print("Give me two numbers, and I'll divide them.") print("Enter 'q' to quit. ") while True: first_number = input("\nFirst number: ") if first_number == 'q': break; second_number = input("\nSecond number: ") if second_number == 'q': break; answer = int(first_number)/int(second_number) print(answer) 获得: liukingdeMacBook-Pro:desktop liuking$ python3 input.py Give me two numbers, and I'll divide them. Enter 'q' to quit. First number: 4 Second number: 2 2.0 First number: 4 Second number: g Traceback (most recent call last): File "input.py", line 244, in <module> answer = int(first_number)/int(second_number) ValueError: invalid literal for int() with base 10: 'g' liukingdeMacBook-Pro:desktop liuking$
经过将可能引起错误的代码放在try-except代码块中,可提升这个程序抵御错误的能力,错误是是执行除法运算的代码行致使的,所以咱们须要将它放到try-except代码块中。依赖于try代码块成功执行的代码都放到else代码块中:
print("Give me two numbers, and I'll divide them.") print("Enter 'q' to quit. ") while True: first_number = input("\nFirst number: ") if first_number == 'q': break; second_number = input("\nSecond number: ") if second_number == 'q': break; try: answer = int(first_number)/int(second_number) except Exception: print("you can't divide by 0!") else: print(answer) 获得: liukingdeMacBook-Pro:desktop liuking$ python3 input.py Give me two numbers, and I'll divide them. Enter 'q' to quit. First number: 5 Second number: 3 1.6666666666666667 First number: 5 Second number: 0 you can't divide by 0! First number:
发现异常也能友好的提示给用户。
try-except-else代码块的工做原理大体以下:python尝试执行try代码块中的代码;只有可能引起异常的代码才须要放在try语句中。有时候,有一些仅在try代码块成功执行时才须要运行的代码,这些代码应该放在else代码块中。except代码块告诉python,若是它尝试运行try代码块中的代码时引起了指定的异常,该怎么办。
经过预测可能发生错误的代码,可编写健壮的程序,它们即使面临无效数据或者缺乏资源,也能继续运行,从而可以抵御无心的用户错误和恶意的***。
通常都是使用模块json来存储数据。
使用json.dump()来存储(写入)数据
import json numbers = [2,3,5,7,9,22,44] file_name = 'numbers.json' with open(file_name,'w') as f_obj: json.dump(numbers,f_obj)
咱们先要导入模块json,再执行,最后能够打开numbers.json文件,看到其内容与python中同样。
再使用json.load()读取numbers.json文件:
import json file_name = 'numbers.json' with open(file_name) as f_obj: numbers = json.load(f_obj) print(numbers) 获得: [2, 3, 5, 7, 9, 22, 44]
与咱们指望的一致。
Python标准库中的模块unitest提供了代码测试工具。单元测试用于测试函数的某个方面是否有问题;测试用例是一组单元测试,这些单元测试一块儿核实函数在各类情形下的行为都符合要求。
#####2.可经过的测试
要为函数编写测试用例,可先导入模块unittest以及要测试的函数,再建立一个继承unittest.TestCase的类,并编写一系列方法对函数行为的不一样方面进行测试。
首先咱们来写一个方法:
def get_formatted_name(first,last): """Generate a neatly formatted full name.""" full_name = first + ' ' + last return full_name.title()
再写一个测试用例
import unittest from name_function import get_formatted_name class NameTestCase(unittest.TestCase): """测试name_function.py""" def test_first_last_name(self): """可以正确地处理Janis Joplin这样的姓名吗?""" formatted_name = get_formatted_name('janis','joplin') self.assertEqual(formatted_name,'Janis Joplin') unittest.main() 获得: . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK
这里咱们给出一个不能经过测试的案例
def get_formatted_name(first,middle,last): """Generate a neatly formatted full name.""" full_name = first + ' ' + middle + ' ' + last return full_name.title() 再运行一下: E ====================================================================== ERROR: test_first_last_name (__main__.NameTestCase) 可以正确地处理Janis Joplin这样的姓名吗? ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/liuking/Desktop/test_name_function.py", line 11, in test_first_last_name formatted_name = get_formatted_name('janis','joplin') TypeError: get_formatted_name() takes exactly 3 arguments (2 given) ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) [Finished in 0.1s with exit code 1]
测试未经过时怎么办?若是检查的条件没错,测试经过了意味着函数的行为是对的,而测试未经过意味着你编写的新代码有错,所以测试未经过时,不要修改测试,而应修复致使测试不能经过的代码:检查刚对函数所作的修改,找到致使函数行为不符合预期的修改。
把刚才的函数代码稍做修改:
def get_formatted_name(first,last,middle = ''): """Generate a neatly formatted full name.""" if middle: full_name = first + ' ' + middle + ' ' + last else: full_name = first + ' ' + last return full_name.title() 获得: . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK [Finished in 0.1s]
又能正确经过测试。
咱们为NamesTestCase再添加一个方法:
# -*- coding: utf8 -*- import unittest from name_function import get_formatted_name class NameTestCase(unittest.TestCase): """测试name_function.py""" def test_first_last_name(self): """可以正确地处理Janis Joplin这样的姓名吗?""" formatted_name = get_formatted_name('janis','joplin') self.assertEqual(formatted_name,'Janis Joplin') def test_first_last_middle_name(self): """可以正确地处理Janis Joplin Kobe这样的姓名吗?""" formatted_name = get_formatted_name('janis','Kobe','joplin') self.assertEqual(formatted_name,'Janis Joplin Kobe') unittest.main() 获得: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK [Finished in 0.1s]
经常使用的断言方法,使用这些方法可核实返回的值等于或不等于预期的值,返回的值为True或False,返回的值在列表中或者不在列表中。只能在继承unittest.TestCase的类中使用这些方法
方法 | 用途 |
---|---|
assertEqual(a,b) | 核实 a ==b |
assertNotEqual(a,b) | 核实 a !=b |
assertTrue(x) | 核实x为True |
assertFalse(x) | 核实x为False |
assertIn(item,list) | 核实item在list中 |
assertNotIn(item,list) | 核实item不在list中 |
类的测试与函数的测试类似--你所作的大部分工做都是测试类中方法的行为,但存在一些不一样之处,
# -*- coding: utf8 -*- class AnonymousSurvey(): """收集匿名调查问卷的答案""" def __init__(self, question): self.question = question self.responses = [] def show_question(self): """显示调查问卷""" print(self.question) def store_response(self,new_response): """存储单份调查问卷""" self.responses.append(new_response); def show_results(self): """显示收集到的全部答案""" print("Survey Results:") for response in self.responses: print('- '+response) ------------------------------------------------------------------------------------------ from survey import AnonymousSurvey #定义一人问题,并建立一个表示调查的AnonymousSurvey对象 question = "What language did you first learn to speak?" my_survey = AnonymousSurvey(question) my_survey.show_question() print("Enter 'q' at any time to quit.\n") while True: response = input("language: ") if response == 'q': break my_survey.store_response(response) #显示调查结果: print("\nThank you to everyone who participated in the survey?") my_survey.show_results() 运行获得: 在终端运行获得: What language did you first learn to speak? Enter 'q' at any time to quit. language: english language: chinese language: japanese language: q Thank you to everyone who participated in the survey? Survey Results: - english - chinese - japanese
下面来编写一个测试,对AnonymousSurvey类的行为的一个方面进行验证:若是用户面对调查问题时只提供一个答案,这个答案也能被妥善保存,为此咱们将在这个答案被保存后,用方法assertIn()来核实包含在答案列表中:
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """docstring for ClassName""" def test_store_single_response(self): question = "what language did you first learn to speak?" my_survey = AnonymousSurvey(question) my_survey.store_response('english') self.assertIn('english',my_survey.responses) unittest.main() 运行获得: . ---------------------------------------------------------------------- Ran 1 test in 0.000s OK [Finished in 0.1s]
这里咱们首先导入了模块unittest以及要测试的类AnonymousSurvey,它也继承于unittest.TestCase第一个测试方法验证调查问题的单个答案被存储后,会包含在调查结果列表中。
只能收集一个答案的调查用途不大,咱们来核实用户提供的三个答案,也将它们存储。
import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """docstring for ClassName""" def test_store_single_response(self): question = "what language did you first learn to speak?" my_survey = AnonymousSurvey(question) my_survey.store_response('english') self.assertIn('english',my_survey.responses) def test_store_three_responses(self): question = "what language did you first learn to speak?" my_survey = AnonymousSurvey(question) responses = ['english','chinese','japanese'] for response in responses: my_survey.store_response(response) for response in responses: self.assertIn(response,my_survey.responses) unittest.main() 运行获得: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK [Finished in 0.1s]
在unittest.TestCase类包含方法setUp(),让咱们只须要建立这些对象一次,并在每一个测试方法中使用他们,若是你在TestCase类中包含了方法setUp(),Python将先运行它,再运行各个以test_打头的方法,这样在咱们编写的每一个测试方法中均可使用方法setUp()中建立的对象。
# -*- coding:utf8 -*- import unittest from survey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): def setUp(self): """建立一个调查对象和一组答案,供使用的测试方法使用。""" question = "What language did you first learn to speak?" self.my_survey = AnonymousSurvey(question) self.responses = ['chinese','english','japanese'] """docstring for ClassName""" def test_store_single_response(self): self.my_survey.store_response(self.responses[0]) self.assertIn(self.responses[0],self.my_survey.responses) def test_store_three_responses(self): for response in self.responses: self.my_survey.store_response(response) for response in self.responses: self.assertIn(response,self.my_survey.responses) unittest.main() 运行获得: .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK [Finished in 0.1s]
方法setUp()让测试方法编写起来更容易,可在setUp()方法中建立一系列并设置他们的属性,再在测试方法中直接使用这些实例,相比于在每一个测试方法中都都建立并设置其属性,这要容易得多。