Python学习笔记
(寒假照着一本书入门了一下Python,在文档里整理了一些基本语法,贴出来以供大家参考)
# 输出: # 直接输出字符串或变量是这样的 print("Hello Python world!") message = "Hello Python world!" print(message) # 输出带变量的字符串是这样的 print(f"message is : {message}") # 变量: # 变量是可以赋给值的标签(指向特定值的指针),不是盒子 # 单引号和双引号是一样的 string1 = "Hello Python world!" string2 = 'Hello Python world!' #可以把两个字符串直接拼起来 string3 = f"{string1} and {string2} are same." # 数字是这样的 int_number = 12 float_number = 12.3 # 数字可以用下划线分组,不影响实际数值 number = 14_000_000_000 number = 140_00_0000_00 # 可以同时给多个变量赋值 x, y, z = 1, 2, 3 # 字符串: name = 'bob love alice' # 自动调整字符串中每个单词的首字母大写和大小写: name.title() name.upper() name.lower() # 换行符与制表符: sentence1 = 'bob\nlove\nalice' sentence2 = 'bob\tlove\talice' # 删除字符串的头/尾/头和尾部空白(空格和换行): word = ' lover ' word.lstrip() word.rstrip() word.strip() # 下面演示了一种创建多行字符串的方式 prompt = "If you tell us who you are, we can personalize the messages you see." prompt += "\nWhat is your first name? \n" name = input(prompt) print(f"Hello, {name}!") # 可以用int函数将字符串转换成整数 age = input("How old are you?\n") print(age) age = int(age) + 1 print(age) # 可以使用方法split将字符串按照某个字符分隔开来(一般是空格) # 该方法的返回值是一个以字符串为元素的列表 string = "1 2 3 4 5" numbers = string.split(' ') print(numbers) # 注释可以写成文档字符串的形式 """ 文档字符串用三引号括起,Python使用他们来生成有关程序中函数的文档 """ # 可以结合使用字符串和列表以获取字符串的某一部分 string = "abcdefghijklmnopqrstuvwxyz" print(string[0:4]) # 可以使用方法replace将字符串中的特定单词都替换为另一个单词 # 该方法的返回值是替换后的字符串 message = "I really like dogs and dogs." new_message = message.replace('dogs', 'cats') print(new_message) # 运算: # 整数可以直接运算 2 + 3 3 - 2 2 * 3 # **是平方 3 ** 2 # 任何除法的结果都是小数,不管能否整除 3 / 2 4 / 2 # 整数可以相互取模 3 % 2 4 % 3 # 小数也可以直接运算 0.1 + 0.1 0.2 + 0.2 # 有时候小数的运算会产生多余小数位的bug 0.2 + 0.1 3 * 0.1 # 在任何运算中,如果有小数参与运算,那么结果是小数 1 + 2.0 3.0 * 2 # 列表: # 用方括号表示列表,类似于数组 cars = ['Benz', 'BMW', 'Audi', 'Toyota'] numbers = [1, 2, 3, 123] # 可以输出整个列表也可以只输出一个元素 print(cars) print(numbers[3]) # 假设列表中有n个元素,那么列表的下标范围是[-n,n-1],共有两个循环 print(cars[-4].title()) print(cars[3].upper()) print(cars[0].lower()) # 可以直接通过指针修改列表中的值 cars[3] = 'Honda' # append可以在列表末尾添加元素,也可以动态创建列表 cars.append('Porsche') # insert可以在列表指定位置的前面添加一个元素,也就是说插入的元素就在指定位置 cars.insert(2, 'Tesla') # del可以永久删除列表中某个特定位置的元素,并且无法访问删除的值 del cars[2] # pop可以永久删除列表中某个特定位置的元素,并且可以访问删除的值 # 如果不指定位置则默认删除尾部元素 car1 = cars.pop() car2 = cars.pop(0) # remove可以根据值删除元素,只删除这个值第一次出现的位置,并且可以访问删除的值 cars.remove('Audi') # 如果这个值不在列表里就会报错 # cars.remove('Tesla') # sort可以对列表永久排序 # 如果不指定排序方式则默认按字典序从小到大 cars.sort() # 也可以从大到小 cars.sort(reverse = True) # sorted可以对列表临时排序 newlist = sorted(cars) # 同样也可以倒序 newlist = sorted(cars, reverse = True) print(newlist) # reverse可以将列表元素的顺序翻转 cars.reverse() # len可以获得列表的长度 length = len(cars) print(length) # for循环: # 可以使用循环遍历列表,是直接访问指针,无需使用下标 names = ['machao', 'lixin', 'laofuzi', 'mengtian'] # 注意python的循环内部语句的标识不是靠括号而是靠缩进 # for循环的运行逻辑可能是将迭代器指向对应的列表后开始向后迭代 # 这个逻辑导致如果在for循环里修改列表可能会导致循环出现问题 # 如果迭代至for后面的条件不满足则退出循环,否则继续迭代 for name in names: print(name.title()) print(name.upper()) print("They are my favorite hero.") # 可以用range来实现一个区间内整数的遍历 # 注意这个区间是左闭右开区间 for value in range(0, 5): print(value) # 可以指定步长 for value in range(0, 5, 2): print(value) # 可以用range创建一个列表 numbers = list(range(0, 5)) # 可以用函数直接获得数字列表的最大值,最小值和总和 min_num = min(numbers) max_num = max(numbers) sum_num = sum(numbers) # 可以用循环嵌套的方式生成列表 numbers = [value ** 2 for value in range(0, 5)] print(numbers) # 可以通过切片直接获取列表的一个部分,返回值同样是一个列表 names = ['machao', 'lixin', 'laofuzi', 'mengtian'] # 注意这里仍然是左开右闭区间 print(names[0:3]) # 第一个索引默认为0 print(names[:3]) # 第二个索引默认为总长度 print(names[1:]) # 可以指定步长 print(names[::2]) # 可以是负数,用法和列表下标是一样的 print(names[-3:]) # 可以用for循环遍历切片 for name in names[0:3]: print(name) # 可以通过切片直接复制列表,复制得到的列表和之前的列表占用不同的空间 spare_names = names[:] # 如果不通过切片复制,那么相当于只复制了指针,前后两个列表占用相同的空间 spare_names = names # 可以判断某个特定值在/不在列表里 print('machao' in names) print('machao' not in names) # 可以判断某个列表是不是空的 names = [] if names: print('非空') else: print('空') # 元组: # 是列表的常量版本 constant = (0, 100) # 修改操作是禁止的 # constant[0] = 1 # 其他的操作与列表一致 # 条件语句: # if语句的基本格式如下(最后一部分的else可以省略) car = 'Audi' company = 'Volkswagen' if (car.lower() == 'benz') and (company.lower() == 'mercedes'): print('梅奔') elif (car.lower() == 'lexus') or (company.lower() == 'toyota'): print('雷车') else: print('奥迪') # 字典: # 字典类似于C++中的map(由一系列键-值对组成),其基本格式如下 car = { 'company': 'toyota', 'name': 'corolla', } print(car['company'].title()) print(car['name'].title()) # 可以直接添加键值对 car['price'] = 20_0000 print(car) # 可以修改键值对 car['company'] = 'honda' print(car) # 可以使用del删除键值对(类似于列表) del car['company'] print(car) # 可以使用get访问键值对,并且在键不存在时避免error message = car.get('company', 'No company value assigned.') print(message) # 可以使用for循环来遍历字典的所有键值对 for key, value in car.items(): print(f"{key}: {value}") # 也可以单独遍历字典的键/值(其中的keys和values两个函数的返回值都是一个列表) for key in sorted(car.keys()): print(f"Key: {key}") for value in car.values(): print(f"Value: {value}") # 列表的元素可以是字典 cars = [] for number in range(0, 4): car = { 'company': 'toyota', 'name': 'corolla', 'price': 200_000, } cars.append(car) print(cars) # 字典的值的元素可以是列表 car = { 'company': ['Mercedes', 'Benz'], 'name': 'G63', } print(car) # 字典的值的元素可以是字典 users = { 'Arthur': { 'first': 'Arthur', 'last': 'Morgan', }, 'John': { 'first': 'John', 'last': 'Marston', }, } print(users) # 集合: # 可以调用set函数对一个列表去重 numbers = [1, 1, 2, 4] print(set(numbers)) # 也可以直接使用花括号定义一个set(注意和字典的定义方式区分) numbers = {1, 1, 2, 4} print(numbers) # 输入: # 可以调用input函数进行输入,其中传递的参数是要向输入用户显示的提示或说明 message = input(f"Tell me sth, and I'll repeat back to you:\n") print(message) # while循环: # for循环用于针对集合中的每个元素都执行一个代码块 # 而while循环则不断运行,直到指定的条件不满足为止 current_number = 1 while current_number <= 5: print(current_number) current_number += 1 # 可以使用break语句以退出循环 # 可以使用continue语句跳过当前循环 while True: message = input() if message == 'break': break elif message == 'continue': continue else: print(message) # 不应在for循环中修改列表,否则将导致python难以跟踪其中的元素 # 要在遍历列表的同时对其进行修改,可使用while循环 users = ['alice', 'bob', 'carol'] confirmed_users = [] while users: current_user = users.pop() print(f"Verifying user: {current_user.title()}") confirmed_users.append(current_user) # 使用while循环删除为特定值的所有列表元素 pets = ['dog', 'cat', 'goldfish', 'cat', 'rabbit', 'cat'] print(pets) while 'cat' in pets: pets.remove('cat') print(pets) #使用用户输入来填充字典 responses = {} polling_active = 1 while polling_active: name = input("\nWhat is your name? ") response = input("Which mountain would you like to climb someday? ") responses[name] = response repeat = input("Would you like to let another person respond?(yes/no) ") if repeat == 'no': polling_active = 0 print("\n--- Poll Results ---") for name, response in responses.items(): print(f"{name} would like to climb {response}.") # 函数: # 可以使用def语句定义函数 def greet_user(): print("Hello!") greet_user() # 可以向函数传递参数 # 其中在定义处的参数叫做形参(parameter) # 在调用处的参数叫做实参(argument) def greet_user(user_name): print(f"Hello! {user_name.title()}") greet_user('Frank') # 实参和形参的关联方式有很多种,最简单的一种是基于实参的顺序,称为位置实参 def greet_user(user_name1, user_name2): print(f"Hello! {user_name1.title()} and {user_name2.title()}") greet_user('Alice', 'Bob') # 另外一种是关键字实参,无需考虑顺序 # 注意一个书写习惯是实参和形参的等号不要空格 greet_user(user_name2='Alice', user_name1='Bob') # 定义函数时可以预先指定某个形参的默认值,后续不需要再次传递该参数 def greet_user(user_name1, user_name2='Bob'): print(f"Hello! {user_name1.title()} and {user_name2.title()}") # 在有默认值时以下两句话是等价的 greet_user('Alice') greet_user(user_name1='Alice') # 可以为函数指定返回值 def get_formatted_name(first_name, last_name): full_name = f"{first_name} {last_name}" return full_name.title() name = get_formatted_name('jimi', 'hendrix') print(name) # 可以让实参变成可选的 def get_formatted_name(first_name, last_name, middle_name=''): if middle_name: full_name = f"{first_name} {middle_name} {last_name}" else: full_name = f"{first_name} {last_name}" return full_name.title() name = get_formatted_name('jimi', 'hendrix') print(name) # 函数的返回值可以是字典 def get_formatted_name(first_name, last_name, age=None): person = {'first': first_name, 'last': last_name} if age: person['age'] = age return person person = get_formatted_name('jimi', 'hendrix', 27) print(person) # 可以将列表作为实参传递给函数 def greet_users(names): for name in names: message = f"Hello, {name.title()}!" print(message) user_names = ['alice', 'bob', 'carol'] greet_users(user_names) # 传递时既可以传递原本的列表,也可以传递一个副本 # 这决定了在函数中修改列表时是否会影响到原本的列表 greet_users(user_names) greet_users(user_names[:]) # 函数可以从调用语句中收集任意数量的实参 # 下面的函数将收集到的实参封装到一个名为names的元组中 def greet_users(*names): print(names) greet_users('Alice', 'Bob', 'Carol') # 可以混合使用位置实参和任意数量实参 def greet_users(age, *names): print(age) print(names) greet_users(18, 'Alice', 'Bob', 'Carol') # 函数可以从调用语句中收集任意数量的关键词实参 # 下面的函数将收集到的关键字实参封装到一个名为user_info的字典中 def greet_users(age, *names, **user_info): user_info['age'] = age user_info['first_name'] = names[0].title() user_info['last_name'] = names[1].title() return user_info user_profile = greet_users(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 可以将函数存储在称为模块的独立文件中 # 使用import打开对应的文件 import model user_profile = model.greet_users(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 也可以导入模块中的特定函数 from model import greet_users user_profile = greet_users(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 导入函数时可以使用as给函数指定别名 from model import greet_users as gu user_profile = gu(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 导入模块时可以使用as给模块指定别名 import model as m user_profile = m.greet_users(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 可以导入模块中的所有函数 from model import * user_profile = greet_users(18, 'albert', 'einstein', location='princeton', field='physics') print(user_profile) # 类: # 面向对象编程编程是最有效的软件编写方法之一 # 在面向对象编程中,我们编写表示现实世界中的事物和情景的类,并基于这些类来创建对象 # 编写类时,我们定义一大类对象都有的通用行为 # 基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性 # 根据类来创建对象称为实例化,这让我们能够使用类的实例 # 下面来编写一个表示小狗的简单类Dog,这个类让Python知道如何创建表示小狗的对象 # 编写这个类后,我们将使用它来创建表示特定小狗的实例 # 根据约定,在Python中,首字母大写的名称指的是类 # 这个类定义中没有圆括号,因为要从空白创建这个类 class Dog: # 类中的函数称为方法,有关函数的一切都适用于方法 # 此处的__init__是一个特殊方法,每当我们根据Dog类创建新实例时,Python都会自动运行它 # 务必确保该方法名称两边有且仅有两个下划线,否则它将不被视为特殊方法 # 在这个方法的定义中,形参self必不可少,而且必须位于其他形参的前面 # 这是因为Python调用这个方法时将会自动传入实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法 # 每当根据Dog类创建实例时,都只需给最后两个形参提供值 def __init__(self, name, age): """初始化属性name和age""" # 此处定义的两个变量都有前缀self,以self为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问 # self.name = name获取与形参name相关联的值,并将其赋给变量name,然后该变量被关联到当前创建的实例 # 像这样可以通过实例访问的变量称为属性 self.name = name self.age = age # 属性可以指定默认值 self.color = 'brown' # 此处的两个方法不是特殊方法,所以名称两边不要有且仅有两个下划线 # 它们执行时不需要额外的信息,因此它们只有一个形参self def sit(self): """模拟小狗收到命令时蹲下""" print(f"{self.name.title()} is now sitting.") def roll_over(self): """模拟小狗收到命令时打滚""" print(f"{self.name.title()} rolled over!") # 可以通过方法修改属性的值 def update_age(self, new_age): self.age = new_age # 下面来创建一个表示特定小狗的实例 # 这里Python使用实参'Willie'和6调用Dog类的方法__init__()创建一个表示特定小狗的实例,并使用提供的值来设置属性name和age # 接下来,Python返回一个表示这条小狗的实例,而我们将这个实例赋值给了变量my_dog # 在这里,命名约定很有用:通常认为首字母大写的名称(如Dog)指的是类,而小写的名称(如my_dog)是根据类创建的实例 my_dog = Dog('Willie', 6) # 可以使用句点表示法访问属性 print(f"My dog's name is {my_dog.name}.") print(f"My dog is {my_dog.age} years old.") # 可以使用句点表示法调用方法 my_dog.sit() my_dog.roll_over() # 可以直接修改属性的值 my_dog.age = 9 print(f"My dog is {my_dog.age} years old.") # 可以通过方法修改属性的值 my_dog.update_age(12) print(f"My dog is {my_dog.age} years old.") # 编写类时,并非总是要从空白开始 # 如果要编写的类是另一个现成类的特殊版本,可使用继承 # 一个类继承另一个类时,将自动获得另一个类的所有属性和方法 # 原有的类称为父类,而新类称为子类 # 子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法 # 例如,下面来模拟柯基犬,柯基犬是一种特殊的狗,因此可在前面创建的Dog类的基础上创建新类CorgiDog # 下面创建CorgiDog类的一个简单版本,它具备Dog类的所有功能 # 创建子类时,父类必须包含在当前文件中,且位于子类前面 # 定义子类时,必须在圆括号内指定父类的名称, class CorgiDog(Dog): def __init__(self, name, age): # 此处的super是一个特殊函数,让我们能够调用父类的方法 super().__init__(name, age) # 可以添加区分子类和父类所需的新属性和新方法 self.butt = 'soft' def walking(self): print(f"{self.name.title()}'s {self.butt} butt is moving.") my_dog = CorgiDog('maika', 3) print(f"{my_dog.name.title()} is {my_dog.age} years old.") my_dog.walking() # 此处无需声明,子类可以使用父类的所有属性和方法 my_dog.roll_over() # 实例可以用作属性(类之间可以嵌套) class Pets: def __init__(self, name, age): self.dog = CorgiDog(name, age) my_pet = Pets('maika', '3') print(f"{my_pet.dog.name.title()} is {my_pet.dog.age} years old.") # Python允许将类存储在模块中,然后在主程序中导入所需的模块 # 下面导入模块car中的Car类 from car import Car my_new_car = Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_new_car.odometer_reading = 23 my_new_car.read_odometer() # 同一个模块中可以存储多个类,同样也可以导入多个类 from car import ElectricCar,Car my_tesla = ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() my_tesla.battery.get_range() # 可以导入整个模块,然后使用句点表示法访问需要的类 import car my_new_car = car.Car('audi', 'a4', 2019) print(my_new_car.get_descriptive_name()) my_tesla = car.ElectricCar('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) # 导入模块中的每个类还可以使用下面的语句 # 但是这样使用容易导致混淆,一般不使用这类语句 # from car import * # 可以在一个模块中导入另一个模块 # 可以在导入时使用别名 from car import ElectricCar as EC my_tesla = EC('tesla', 'model s', 2019) print(my_tesla.get_descriptive_name()) my_tesla.battery.describe_battery() my_tesla.battery.get_range() # 可以使用Python标准库中的任何函数和类 from random import randint print(randint(1, 6)) from random import choice players = ['alice', 'bob', 'carol', 'dave'] print(f"{choice(players).title()}") # 一些需要注意的编码风格问题: # 类名应该采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线 # 实例名和模块名都采用小写格式,并且在单词之间加上下划线 # 对于每个类,都应该紧跟在类定义后面包含一个文档字符串 # 这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定 # 每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述 # 可使用空行来组织代码,但不要滥用 # 在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类 # 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句 # 再添加一个空行,然后编写导入你自己编写的模块的import语句 # 文件与异常: # 下面演示如何读取文件,并将文件内容作为一个长字符串context存储 with open('words.txt', 'r') as file_object: context = file_object.read() print(context.title()) # 可以使用绝对路径读取文件 # 代码中可以使用斜杠和反斜杠,如果使用反斜杠需要写成\\而不是\ with open('C:/Users/yin_s/Desktop/Code/python/words.txt', 'r') as file_object: context = file_object.read() print(context.title()) # 可以逐行读取文件中的内容 with open('words.txt', 'r') as file_object: for line in file_object: print(line.rstrip().title()) # 可以创建一个包含文件各行内容的列表 with open('words.txt', 'r') as file_object: lines = file_object.readlines() print(lines) # 下面演示如何将程序的输出写入文件(文件原本的内容会被完全覆盖掉) with open('out.txt', 'w') as file_object: file_object.write("I love programming.") # 写入多行时需要注意write函数不会在文件的末尾添加换行符(不同于print) with open('out.txt', 'w') as file_object: file_object.write("I love programming.\n") file_object.write("I love creating new games.\n") # 如果要给文件添加内容(而不是覆盖原有的内容),可以以附加模式'a'打开文件 with open('out.txt', 'a') as file_object: file_object.write('I also love finding meaning in large datasets.\n') # Python使用称为异常的特殊对象来管理程序执行期间发生的错误 # 每当发生让Python不知所措的错误时,它都会创建一个异常对象 # 如果你编写了处理该异常的代码,程序将继续运行 # 如果未对异常进行处理,程序将停止并显示traceback,其中包含有关异常的报告 # 异常是使用trace-except-else代码块处理的,下面演示如何用它处理除0错 a = 5 b = 0 try: ans = int(a) / int(b) except ZeroDivisionError: # Python有一个pass语句可以执行“什么都不做”的操作 pass else: print(ans) # json模块的使用: # 模块json能让我们将结构简单的python数据转储到文件中,并在程序再次运行时加载该文件中的数据 # 还可以使用json在python程序之间分享数据 # 更重要的是,JSON数据格式并非Python专用的,这让我们能够将以JSON格式存储的数据与使用其他编程语言的人分享 # 注意:JSON格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用 # 下面演示如何使用json.dump来存储数字列表 import json numbers = [2, 3, 5, 7, 11, 13] with open('numbers.json', 'w') as f: json.dump(numbers, f) # 下面演示如何使用json.load将列表读取到内存中 with open('numbers.json', 'r') as f: numbers = json.load(f) print(numbers) # 测试: # 编写函数或类时,还可为其编写测试 # 通过测试,即可确定代码面对各种输入都能够按要求的那样工作 # Python标准库中的模块unittest提供了代码测试工具 # 单元测试用于核实函数的某个方面没有问题 # 测试用例是一组单元测试,它们一道核实函数在各种情形下的行为都符合要求 # 全覆盖的测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式 # 下面演示如何检查函数get_formatted_name在给定名和姓时能否正确工作 import unittest from test import get_formatted_name class NamesTestCase(unittest.TestCase): """测试test.py""" def test_first_last_name(self): formatted_name = get_formatted_name('janis', 'joplin') # 此处使用断言方法核实得到的结果是否与期望的结果一致 self.assertEqual(formatted_name, 'Janis Joplin') def test_first_middle_last_name(self): formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus') self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart') # 很多测试框架都会先导入测试文件再运行 # 导入文件时,解释器将在导入的同时执行它 # 此处的if代码块检查特殊变量__name__,这个变量是在程序执行时设置的 # 如果这个文件作为主程序执行,变量__name__将被设置为'__main__',此时需要调用unittest.main()来运行测试用例 # 如果这个文件被测试框架导入,变量__name__的值将不是'__main__',因此不会调用unittest.main() if __name__ == '__main__': unittest.main() # 下面来演示如何编写针对类的测试 import unittest from anonymoussurvey import AnonymousSurvey class 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) """针对AnonymousSurvey类的测试""" def test_store_three_response(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) if __name__ == '__main__': unittest.main() # 在前面的测试中,我们在每个测试方法中都创建了一个AnonymousSurvey实例,并在每个方法中都创建了答案 # unittest.TestCase类包含的方法setUp()让我们只需创建这些对象一次,就能在每个测试方法中使用 # 如果在TestCase类中包含了方法setUp(),Python将先运行它,再运行各个以test_打头的方法 # 下面演示如何使用setUp()来创建一个调查对象和一组答案 import unittest from anonymoussurvey import AnonymousSurvey class TestAnonymousSurvey(unittest.TestCase): """针对AnonymousSurvey类的测试""" 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) """针对AnonymousSurvey类的测试""" def test_store_three_response(self): """测试三个答案会被妥善地存储""" for response in self.responses: self.my_survey.store_response(response) for response in self.responses: self.assertIn(response, self.my_survey.responses) if __name__ == '__main__': unittest.main()