三剑客python自学笔记--06
Python编程:从入门到实践 链接:https://pan.baidu.com/s/1kbseKVhMm-O9EphvF4V3XA
提取码:3a4r
Python编程快速上手—让繁琐工作自动化 链接:https://pan.baidu.com/s/1knrfzj22huEBWWdQBnRdXA
提取码:8g5k
Python极客项目编程 链接:链接:https://pan.baidu.com/s/1Jo7lYyTEFnpnG3mou7uPmw
提取码:97dm
10-11章笔记:
#文件和异常
#从文件中读取数据
#读取整个文件
with open('pi_digits.txt') as file_object:#关键字with在不需要访问文件后将其关闭。使用open(),close()易出错contents = file_object.read()#使用方法read()读取这个文件的全部内容print(contents.rstrip())
#read()到达文件末尾时返回一个空字符串,而将这个空字符串显示出来就是一个空行。
#使用rstrip()删除字符串末尾的空白(但实际并没有可删除的空白)
#Python在当前执行的文件所在的目录中查找指定的文件。函数open()返回一个表示文件的对象#文件路径
#如果所读取文件和程序并不在同一目录,则需要提供文件的路径#相对路径
#读取子目录里的文件
#例,读取文件夹python_work下的文件夹text_files中查找指定的.txt文件
#windows系统中:
#with open('text_files\filename.txt') as file_object:#绝对文件路径
#将文件在计算机中的准确位置告诉Python,这样就不用关心当前运行的程序存储在什么地方了
#绝对路径通常比相对路径更长,因此将其存储在一个变量中,再将该变量传递给open()
#在Windows系统中:
#file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
#with open(file_path) as file_object:#逐行读取
print(" ")filename = 'pi_digits.txt'with open(filename) as file_object:#使用关键字with ,让Python负责妥善地打开和关闭文件for line in file_object:print(line)#这样的话,我们打印每一行时,就会有一行空白行#按书上的说法,没打印一行有两行空白行,解释是为在这个文件中,每行的末尾都有一个看不见的换行符,而print 语句也会加上一个换行符
#因此每行末尾都有两个换行符:一个来自文件,另一个来自print 语句#但实际操作中并没有出现这种情况,目前原因未知#消除这些多余的空白行,可在print 语句中使用rstrip():
filename = 'pi_digits.txt'with open(filename) as file_object:for line in file_object:print(line.rstrip())#创建一个包含文件各行内容的列表#使用关键字with 时,open() 返回的文件对象只在with 代码块内可用。如果要在with 代码块外访问文件的内容,
#可在with 代码块内将文件的各行存储在一个列表中,并在with 代码块外使用该列表:你可以立即处理文件的各个部分,也可推迟到程序后面再处理filename = 'pi_digits.txt'with open(filename) as file_object:lines = file_object.readlines()#方法readlines() 从文件中读取每一行,并将其存储在一个列表中;接下来,该列表被存储到变量lines 中
#在with 代码块外,我们依然可以使用lines这个变量for line in lines:#打印列表的每一项时会自动在该项后面添加换行符print(line.rstrip())#使用文件的内容
filename = 'pi_digits.txt'with open(filename) as file_object:lines = file_object.readlines()pi_string = ''
for line in lines:pi_string += line.rstrip() print(pi_string)
print(len(pi_string))#rstrip()删除字符串末尾的空格或换行符,lstrip()删除字符串开头的空格或换行符,strip()删除字符串首尾的空格或换行符
#在变量pi_string 存储的字符串中,包含原来位于每行左边的空格,为删除这些空格,可使用strip() 而不是rstrip() :filename = 'pi_digits.txt'with open(filename) as file_object:lines = file_object.readlines()pi_string = ''
for line in lines:pi_string += line.strip()print(pi_string)
print(len(pi_string))#注意 读取文本文件时,Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,
#就必须使用函数int() 将其转换为整数,或使用函数float() 将其转换为浮点数。#包含一百万位的大型文件filename = 'pi_million_digits.txt'with open(filename) as file_object:lines = file_object.readlines()pi_string = ''
for line in lines:pi_string += line.strip()print(pi_string[:52] + "...")
print(len(pi_string))#圆周率中包含你的生日吗
'''
filename = 'pi_million_digits.txt'with open(filename) as file_object:lines = file_object.readlines()pi_string = ''
for line in lines:pi_string += line.rstrip()birthday = input("Enter your birthday,in the form mmddyy: ")
if birthday in pi_string:print("Your birthday appears in the first million digits of pi!")
else:print("Your birthday does not appear in the first million digits of pi.")'''#方法replace():
message = "I really like dogs."message = message.replace('dog','cat')#C++函数对调用的变量直接修改,Python是返回修改后的变量。两者直观的区别是,Python函数调用是多了赋值这一步。print(message)#写入文件#保存数据的最简单的方式之一是将其写入到文件中。通过将输出写入文件,即便关闭包含程序输出的终端窗口,这些输出也依然存在:
#你可以在程序结束运行后查看这些输出,可与别人分享输出文件,还可编写程序来将这些输出读取到内存中并进行处理。filename = 'programming.txt'with open(filename,'w') as file_object:file_object.write("I love programming.")#使用函数write()#这里open()提供了两个实参。第一个实参是打开的文件的名称;第二个实参('w')告诉Python,我们要以写入模式打开这个文件。
#打开时,可指定读取模式('r')、写入模式('w')、附加模式('a')或让你能够读取和写入文件的模式('r+')。如果省略了模式实参
#Python将以默认的只读模式打开文件。#注意 如果要写入的文件不存在,函数open()讲自动创建它。然而,以写入('w')模式打开文件时千万要小心,因为如果指定的文件已经存在,
#Python将在返回对象前清空该文件。#注意 Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str() 将其转换为字符串格式。#写入多行
#函数write()不会在你写入的额文本末尾添加换行符,因此如果写入多行时没有指定换行符,文件也并不会向想象中的那样换行
#要让每个字符串都单独占一行,需要在write()语句中包含换行符:
filename = 'programming.txt'with open(filename,'w') as file_object:file_object.write("I love programming.\n")file_object.write("I love creating new games.\n")#像显示到终端的输出一样,还可以使用空格、制表符和空行来设置这些输出的格式。#附加到文件#如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式 打开文件。你以附加模式打开文件时,Python不会在返回文件对象前清空文件
#而你写入到文件的行都将添加到文件末尾。如果指定的文件不存在,Python同样会为你创建一个空文件。filename = 'programming.txt'with open(filename,'a') as file_object:#指定实参'a',以便将内容附加到文件末尾,而不是覆盖文件原来的内容。file_object.write("I also love finding meaning in large datasets.\n")#这里还是调用write()file_object.write("I love creating apps that can run in a browser.\n")#异常#Python使用被称为异常 的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。
#如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。
#异常是使用try-except 代码块处理的。try-except 代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。
#使用了try-except 代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。'''
print(5/0)显然,Python无法这样做,因此此时会看到一个traceback:Traceback (most recent call last):File "D:\python_work\hello_world.py", line xxxx, in print(5/0)
ZeroDivisionError: division by zero'''#使用try-except代码块#当你认为可能发生了错误时,可编写一个try-except 代码块来处理可能引发的异常。你让Python尝试运行一些代码,
#并告诉它如果这些代码引发了指定的异常,该怎么办。处理ZeroDivisionError 异常的try-except 代码块类似于下面这样:try:print(5/0)
except ZeroDivisionError:print("You can't divide by zero!")#我们将导致错误的代码行print(5/0) 放在了一个try 代码块中。如果try 代码块中的代码运行起来没有问题,Python将跳过except 代码块;
#如果try 代码块中的代码导致了错误,Python将查找这样的except 代码块,并运行其中的代码,即其中指定的错误与引发的错误相同。
#而如果try-except 代码块后面还有其他代码,程序将接着运行,因为已经告诉了Python如何处理这种错误。#这样,用户看到的是一条友好的错误消息,而不是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':breaksecond_number = input("Second number:")if second_number == 'q':breakanswer = int(first_number) / int(second_number)print(answer)'''
#这个程序没有采取任何处理错误的措施,因此让它执行除数为0的除法运算时,它将崩溃
'''
Give me two numbers, and I'll divide them.
Enter 'q' to quit.First number: 5
Second number: 0
Traceback (most recent call last):File "division.py", line xxxx, in answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero
'''#程序崩溃可不好,但让用户看到traceback也不是好主意。不懂技术的用户会被它们搞糊涂,而且如果用户怀有恶意,
#他会通过traceback获悉你不希望他知道的信息。例如,他将知道你的程序文件的名称,还将看到部分不能正确运行的代码。
#有时候,训练有素的攻击者可根据这些信息判断出可对你的代码发起什么样的攻击。#else代码块#通过将可能引发错误的代码放在try-except 代码块中,可提高这个程序抵御错误的能力。错误是执行除法运算的代码行导致的,
#因此我们需要将它放到try-except 代码块中。这个示例还包含一个else 代码块;依赖于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':breaksecond_number = input("Second number:")if second_number == 'q':breaktry:answer = int(first_number) / int(second_number)except ZeroDivisionError:print("You can't divide by 0!")else:print(answer)'''
#ry-except-else 代码块的工作原理大致如下:Python尝试执行try 代码块中的代码;只有可能引发异常的代码才需要放在try 语句中。
#有时候,有一些仅在try 代码块成功执行时才需要运行的代码;这些代码应放在else 代码块中。except 代码块告诉Python,
#如果它尝试运行try 代码块中的代码时引发了指定的异常,该怎么办。#处理FileNotFoundError异常
'''
filename = 'alice.txt'with open(filename) as f_obj:contents = f_obj.read()'''#Python无法读取不存在的文件,因此它引发一个异常:
'''
Traceback (most recent call last):File "alice.py", line xxxx, in with open(filename) as f_obj:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
'''#在上述traceback中,最后一行报告了FileNotFoundError 异常,这是Python找不到要打开的文件时创建的异常。
#在这个示例中,这个错误是函数open() 导致的,因此要处理这个错误,必须将try 语句放在包含open() 的代码行之前:filename = 'alice.txt'try:with open(filename) as f_obj:contents = f_obj.read()
except FileNotFoundError:msg = "Sorry,the file " + filename + " does not exist."print(msg)#分析文本#方法split() ,它根据一个字符串创建一个单词列表。下面是对只包含童话名"Alice in Wonderland" 的字符串调用方法split() 的结果:
title = "Alice in Wonderland"
print(title.split())#调用split()会返回一个列表filename = 'alice.txt'try:with open(filename) as f_obj:contents = f_obj.read()
except FileNotFoundError:msg = "Sorry,the file " + filename + " does not exist."print(msg)
else:#计算文件大致包含多少个单词words = contents.split()num_words = len(words)print("The file " + filename + " has about " + str(num_words) + " words.")def count_words(filename):"""计算一个文件大致包含多少个单词"""try:with open(filename,encoding='utf-8') as f_obj:#将python读取模式的编码从默认的gbk改变成utf-8,这样就可以读取编码为带BOM的utf-8contents = f_obj.read()except FileNotFoundError:msg = "Sorry,the file " + filename + " does not eexist."print(msg)else:#计算文件大致包含多少个单词words = contents.split()num_words = len(words)print("The file " + filename + " has about " + str(num_words) +" words.")filename = 'alice.txt'
count_words(filename)#现在可以编写一个简单的循环,计算要分析的任何文本包含多少个单词了。为此,我们将要分析的文件的名称存储在一个列表中,
#然后对列表中的每个文件都调用count_words()。我们将尝试计算 Alicein Wonderland 、Siddhartha 、Moby Dick 和 Little Women
#分别包含多少个单词,它们都不受版权限制。我故意没有将siddhartha.txt放到word_count.py所在的目录中,
#让你能够看到这个程序在文件不存在时处理得有多出色:filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']#这里的moby_dick.txt的编码时带BOM的utf-8
for filename in filenames:count_words(filename)#在这个示例中,使用try-except 代码块提供了两个重要的优点:避免让用户看到traceback;让程序能够继续分析能够找到的其他文件。
#如果不捕获因找不到siddhartha.txt而引发的FileNotFoundError 异常,用户将看到完整的traceback,而程序将在尝试分析 Siddhartha
#停止运行——根本不分析 Moby Dick 和 Little Women 。#失败时一声不吭#捕获到异常时一声不吭def count_words(filename):"""计算一个文件大致包含多少个单词"""try:with open(filename,encoding='utf-8') as f_obj:contents = f_obj.read()except FileNotFoundError:passelse:#计算文件大致包含多少个单词words = contents.split()num_words = len(words)print("The file " + filename + " has about " + str(num_words) +" words.")filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']#这里的moby_dick.txt的编码时带BOM的utf-8
for filename in filenames:count_words(filename)#现在,出现FileNotFoundError 异常时,将执行except 代码块中的代码,但什么都不会发生。这种错误发生时,不会出现traceback,也没有任何输出。
#用户将看到存在的每个文件包含多少个单词,但没有任何迹象表明有一个文件未找到:#pass 语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这里做些什么。例如,在这个程序中,
#我们可能决定将找不到的文件的名称写入到文件missing_files.txt中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到的问题。#决定报告哪些错误#存储数据(模块json)
#注意 JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用。#使用json.dump()和json.load()
#我们来编写一个存储一组数字的简短程序,再编写一个将这些数字读取到内存中的程序。第一个程序将使用json.dump() 来存储这组数字,
#而第二个程序将使用json.load() 。
#函数json.dump() 接受两个实参:要存储的数据以及可用于存储数据的文件对象。下面演示了如何使用json.dump() 来存储数字列表:import jsonnumbers = [2, 3, 5, 7, 11, 13]filename = 'numbers.json'
with open(filename, 'w') as f_obj: json.dump(numbers, f_obj)#本文件目录下会出现名为numbers.json的JSON文件
#下面在使用json.load()将这个列表读取到内存中import jsonfilename = 'numbers.json'
with open(filename) as f_obj:numbers = json.load(f_obj)print(numbers)#保存和读取用户生成的数据import json#如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并加载它filename = 'username.json'
try:with open(filename) as f_obj:username = json.load(f_obj)
except FileNotFoundError:username = input("What is your name? ")with open(filename,'w') as f_obj:json.dump(username,f_obj)print("We'll remember you when you come back, " + username + "!")
else:print("Welcome back, " + username + "!")#重构
#你经常会遇到这样的情况:代码能够正确地运行,但可做进一步的改进——将代码划分为一系列完成具体工作的函数。这样的过程被称为重构。
#重构让代码更清晰、更易于理解、更容易扩展。#先将所有代码都放到一个名为greet_user()的函数中:import json
def greet_user():"""问候用户,并指出其名字"""filename = 'username.json'try:with open(filename) as f_obj:username = json.load(f_obj)except FileNotFoundError:username = input("What is your name? ")with open(filename, 'w') as f_obj:json.dump(username, f_obj)print("We'll remember you when you come back, " + username + "!")else:print("Welcome back, " + username + "!")greet_user()#函数greet_user()所做的不仅仅是问候用户,还在存储了用户名时获取它,而在没有存储用户名时提示用户输入一个#下面来重构greet_user(),让它不执行这么多任务。为此,我们首先将获取的用户名的代码移到另一个函数中:
import jsondef get_stored_username():"""问候用户,并指出其名字"""filename = 'username.json'try:with open(filename) as f_obj:username = json.load(f_obj)except FileNotFoundError:return Noneelse:return usernamedef greet_user():"""问候用户,并指出其名字"""username = get_stored_username()if username:print("Welcome back, " + username + "!")else:username = input("What is your name? ")filename = 'username.json'with open(filename,'w') as f_obj:json.dump(username,f_obj)print("We'll remember you when you come back,, " + username + "!")greet_user()#还能继续重构代码:import jsondef get_stored_username():"""问候用户,并指出其名字"""filename = 'username.json'try:with open(filename) as f_obj:username = json.load(f_obj)#这两行代码任一行发生FileNotFoundError都会立刻转到except行except FileNotFoundError:return Noneelse:return usernamedef get_new_username():"""提示用户输入用户名"""username = input("What is your name? ")filename = 'username.json'with open(filename,'w') as f_obj:json.dump(username,f_obj)return usernamedef greet_user():"""问候用户,并指出其名字"""username = get_stored_username()if username:print("Welcome back, " + username + "!")else:username = get_new_username()print("We'll remember you when you come back, " + username + "!")greet_user()#测试代码
'''
from name_function import get_formatted_name#导入函数时不需加()print("Enter 'q' at any time to quit.")
while True:first = input("\nPlease give me a first name: ")if first == 'q':breaklast = input("Please give me a last name: ")if last == 'q':breakformatted_name = get_formatted_name(first,last)print("\tNeatly formatted name: " + formatted_name + ".")
'''#手动测试太繁琐,应自动测试!#Python标准库中的模块unittest 提供了代码测试工具。单元测试 用于核实函数的某个方面没有问题;测试用例 是一组单元测试,
#这些单元测试一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。
#全覆盖式测试 用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。
#通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。、#要为函数编写测试用例,可先导入模块unittest 以及要测试的函数,再创建一个继承unittest.TestCase 的类,
#并编写一系列方法对函数行为的不同方面进行测试。
'''
import unittest
from name_function import get_formatted_nameclass NameTestCase(unittest.TestCase):#创建一个类用于单元测试"""测试name_function.py"""def test_first_last_name(self):"""能够正确地处理像Janis Joplin这样的姓名吗?"""ormatted_name = get_formatted_name('janis','joplin')#调用测试函数self.assertEqual(formatted_name,'Janis Joplin')#断言方法,调用类里的属性和方法都得使用self.+方法名,函数名的格式(自己猜的)unittest.main()
'''
#首先,我们导入了模块unittest 和要测试的函数get_formatted_name() 。
#创建了一个名为NamesTestCase 的类,用于包含一系列针对get_formatted_name() 的单元测试
#你可随便给这个类命名,但最好让它看起来与要测试的函数相关,并包含字样Test。这个类必须继承unittest.TestCase 类,这样Python才知道如何运行你编写的测试。
#将这个方法命名为test_first_last_name() ,一方面因为我们要核实的是只有名和另一方面在运行程序时所有以test 打头的方法都将自动运行。#此外,我们使用了unittest 类最有用的功能之一:一个断言 方法。断言方法用来核实得到的结果是否与期望的结果一致。在这里,
#我们知道get_formatted_name() 应返回这样的姓名,即名和姓的首字母为大写,且它们之间有一个空格,
#因此我们期望formatted_name 的值为Janis Joplin 。为检查是否确实如此,我们调用unittest 的方法assertEqual() ,
#并向它传递formatted_name 和'Janis Joplin' 。代码行self.assertEqual(formatted_name, 'Janis Joplin') 的意思是
#说:“将formatted_name 的值同字符串'Janis Joplin' 进行比较,如果它们相等,就万事大吉,如果它们不相等,跟我说一声!”#最后得到的输出结果形式如下
'''
.
----------------------------------------------------------------------
Ran 1 test in 0.000sOK
'''
#第1行的句点表明有一个测试通过了。接下来的一行指出Python运行了一个测试,消耗的时间不到0.001秒。最后的OK 表明该测试用例中的所有单元测试都通过了。#不能通过的测试
'''
def get_formatted_name(first, middle, last):"""生成整洁的姓名"""full_name = first + ' ' + middle + ' ' + lastreturn full_name.title()
'''
#例如,改变函数get_formatted_name(),让它要求通过一个实参指定中间名(此时再测试就会显示未通过了)#测试未通过会返回一个详细的traceback,告知问题出现在哪里,并会在输出的结尾提示FAILLED(errors=x),告诉你有多少测试未通过#测试未通过时怎么办#如果你检查的条件没错,测试通过了意味着函数的行为是对的,而测试未通过意味着你编写的新代码有错。因此,测试未通过时,不要修改测试,
#而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。'''
#发现是形参的个数不匹配,于是对函数再次进行修改
def get_formatted_name(first, last, middle=''):#设置一个可选的形参(可选的形参要列在最后)"""生成整洁的姓名"""if middle:full_name = first + ' ' + middle + ' ' + lastelse:full_name = first + ' ' + lastreturn full_name.title()
'''
#现在,测试用例又能通过了#添加新测试
#确定get_formatted_name() 又能正确地处理简单的姓名后,我们再编写一个测试,用于测试包含中间名的姓名。为此,我们在NamesTestCase 类中再添加一个方法:
'''
import unittest
from name_function import get_formatted_nameclass 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):"""能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗? """formatted_name = get_formatted_name('wolfgang','mozart','amadeus')self.assertEqual(formatted_name,'Wolfgang Amadeus Mozart')unittest.main()
'''#该编译器不会编译unittest.main()后面的内容#总结
#当为函数增加新功能时,往往容易使原测试用例失败,此时就需要调整函数使其不失原来的功能(即让原来的测试用例可以通过),再添加一个新的测试用例,以检查函数新增的功能#测试类
#针对类的测试(这么看来还是C++的debug方便)#各种断言方法#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中#一个要测试的类
#类的测试与函数的测试相似——你所做的大部分工作都是测试类中方法的行为,但存在一些不同之处,下面来编写一个类进行测试。来看一个帮助管理匿名调查的类:#书上的AnonymousSurvey类编的有点问题,调用属性时没有在其前面加self.,我自己修改了一下#为证明AnonymousSurvey 类能够正确地工作,我们来编写一个使用它的程序:
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':breakmy_survey.store_response(response)#显示调查结果
print("\nThank you to everyone who participated in the survey!")
my_survey.show_results()
'''
#手动测试不好,要自动测试才好#测试AnonymousSurvey
'''
#首先导入模块unittest 以及要测试的类AnonymousSurvey
import unittest
from survey import AnonymousSurveyclass TestAnonmyousSurvey(unittest.TestCase):"""针对AnonymousSurvey类的测试"""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()
'''
#只能收集一个答案的调查用途不大。下面来核实用户提供三个答案时,它们也将被妥善地存储。为此,我们在TestAnonymousSurvey 中再添加一个方法:
'''
import unittest
from survey import AnonymousSurveyclass TestAnonymousSurvey(unittest.TestCase):"""针对AnonymousSurvey类的测试"""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','Spanish','Mandarin']for response in responses:my_survey.store_response(response)for response in responses:self.assertIn(response,my_survey.responses)unittest.main()
'''
#前述做法的效果很好,但这些测试有些重复的地方。下面使用unittest 的另一项功能来提高它们的效率。#方法setUp()
#在前面的test_survey.py中,我们在每个测试方法中都创建了一个AnonymousSurvey 实例,并在每个方法中都创建了答案。
#unittest.TestCase 类包含方法setUp() ,让我们只需创建这些对象一次,并在每个测试方法中使用它们。
#如果你在TestCase 类中包含了方法setUp() ,Python将先运行它,再运行各个以test_打头的方法。这样,在你编写
#的每个测试方法中都可使用在方法setUp() 中创建的对象了。#下面使用setUp() 来创建一个调查对象和一组答案,供方法test_store_single_response() 和test_store_three_responses() 使用:
import unittest
from survey import AnonymousSurveyclass TestAnonmousSurvey(unittest.TestCase):"""针对AnonmousSurvey类的测试"""def setUp(self):"""创建一个调查对象和一组答案,供使用的测试方法使用"""question = "What language did you first learn to speak?"self.my_survey = AnonymousSurvey(question)self.responses = ['English','Spanish','Mandarin']#建立并存储两个属性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()#将调查对象和答案列表储存在属性中,因此可以在这个类地任何地方使用!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
