标签:blog not 一个 修复 语句 sel 对象 href 检查
如果没有看基础部分第一章,请前往Python基础知识两部曲:一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‘是一个实参。
需要注意参数的位置
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.
关键字实参是传递给函数的名称-值对,直接在实参中将名称和值关联起来,因此向函数传递实参时不会混淆。与参数顺序无关。
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.
编写函数可以给每个形参指定默认值,
# 注意已经设置了默认值的参数要放在后面,
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.
调用返回值的函数时,需要提供一个变量,用于存储返回的值。
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
上面我们发现得到一样的结果,但使用了函数处理可以做到复用,且逻辑比较清晰,易于扩展。
如果我们像备份之前的数据,我们就不能修改未认证的用户,这个时候我们可以用切片来处理我们的操作了。
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()方法中创建一系列并设置他们的属性,再在测试方法中直接使用这些实例,相比于在每个测试方法中都都创建并设置其属性,这要容易得多。
标签:blog not 一个 修复 语句 sel 对象 href 检查
原文地址:http://blog.51cto.com/7200087/2070283