zoukankan      html  css  js  c++  java
  • 《Python编程从入门到实践》基础知识个人笔记

    【美】Eric Matthes 2016年7月第1版

    第2章 变量和简单数据类型

    2.2 变量

    2.2.1 变量的命名规则

    • 变量名字只能包含字母、数字和下划线
    • 且不能以数字开头
    • 不能包含空格
    • 不要使用内置关键字和函数名
    • 变量名要见名识义
    • 慎用小写字母l和大写字母O

    2.3 字符串

    2.3.1 使用方法修改字符串的大小写

    • title( )首写字母大写的方式显示每个单词
    name = "peter"
    print(name.title())
    
    • upper( )将字符串改为全部大写
    • lower( )将字符串改为全部小写

    2.3.2 合并(拼接)字符串

    • 可以直接使用+来合并字符串

    2.3.3 使用制表符或换行符来添加空白

    • 制表符 (4个空格)
    • 换行符

    2.3.4 删除空白

    • strip( )删除字符串开头和结尾多余的空白
    • ltrip( )删除字符串开头多余的空白
    • rtrip( )删除字符串结尾多余的空白

    注意:这种删除只是暂时的,再次访问变量值时会恢复,要永久删除空白,必须删除操作过后存回变量中。

    name = "  peter "
    name = name.strip()
    

    第3章 列表简介

    3.1 列表是什么

    • 列表是一系列按特定顺序排列的元素组合
    • 用方括号[ ]表示列表,并用逗号分隔其中的元素
    • 通常用复数的名称命名,如names,letters

    3.1.1 访问列表元素

    • 通过元素索引并将其放在方括号内(注意索引差一的特征)
      print(list[0])
    • 将索引指定为-1时,返回列表中最后一个元素

    3.2.1 修改列表元素

    • 指定列表名和要修改的元素索引,再赋予新值
    name[0] = "Jack"
    

    3.2.2 在列表中添加元素

    • append( )在列表末尾添加元素
      name.append("Ken")
    • insert( )在列表的指定位置添加新元素
      name.insert(0,"Mark")

    3.2.3从列表中删除元素

    1.使用del语句删除元素(前提要知道删除元素的位置)

    • del name[0]值从列表删除后无法再访问

    2、使用方法pop( )删除元素

    • 该方法可以删除列表末尾的元素,并接着使用它的值(弹出)
      name_pop = name.pop()

    3、弹出列表中任何位置处的元素
    name_pop = name.pop(0)

    注意:每当使用pop( )时,被弹出的元素就不在该列表中了

    4、根据值删除元素

    • remove( )只有知道要删除元素的值时使用
    • 使用 remove( )从列表中删除元素时,也可以接着使用它的值

    注意:方法remove( )只删除第一个指定的值。如果要删除的值可能在列表中出现多次,就需要使用循环来判断是否删除了所有这样的值。

    3.3 组织列表

    3.3.1 使用方法sort()对列表进行永久性排序

    • 可以实现列表按字母顺序排列,传递参数reverse = True可以相反顺序排列元素
      name.sort(reverse = True)

    3.3.2 使用函数sorted()对列表进行临时排序

    3.3.3 倒着打印列表

    • 使用方法reverse()反转列表元素的排列顺序,name.reverse()
    • 虽然也是永久性地修改列表元素的排列顺序,但可以随时再次调用reverse()恢复原来的排列顺序

    3.3.4 确定列表的长度

    • len( )函数可以快速获悉列表的长度(列表包含多少个元素)

    第4章 操作列表

    4.1 遍历(for循环)

    4.3 创建数值列表

    4.3.1 使用函数range( )

    • 该函数有差一特征,要打印数字1~5,使用代码range(1,6)
    • 使用range()创建数字列表,并可以设置步长
      numnbers = list(range(2,11,2))

    4.3.4 列表解析

    • 列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素
      squares = [value**2 for value in range(1,11)]

    4.4 列表切片

    • 差一行为:要输出列表中的前三个元素,需要指定索引0~3,分别输出为0,1和2的元素numbers[0:3]
    • 要提取列表的第2~4个元素,可将起始索引指定为1,终止索引指定为4number[1:4]
    • 若起始索引省略,代表从列表头开始number[:3],同样终止索引也可以省略,代表到列表尾number[2:]
    • 负数索引返回离列表末尾相应距离的元素,如输出最后三个元素number[-3:]
    • 复制列表,方法是同时省略起始索引和终止索引number[:]

    4.5 元组

    • 不能修改的值称为不可变的,而不可变的列表被称为元组,使用圆括号()标识

    4.5.3 修改元组变量

    • 虽然不能修改元组的元素,但可以给存储元组的变量赋值,因为给元组变量赋值是合法的
    demensions = (200,50)
    demensions = (400,100)
    

    4.6 设置代码格式

    • Python改进提案(Python Enhancement Proposal,PEP),其中PEP8是最古老的PEP之一
    • 代码行长建议不超过80字符,注释行长不超过72字符,不可逾越红线99字符

    第5章 if语句

    5.2 条件测试

    • 检查是否相等用==,一个等号是陈述,两个等号是发问
    • 检查是否相等时区分大小写
    • 检查是否不相等用=!
    • 检查多个条件,age >= 10 and age<= 21
    • 检查特定值是否包含在列表中,使用关键字in,如'paul' in names返回布尔值
    • 检查特定值是否不包含在列表中,使用关键字not in

    5.3.3 if-elif-else语句

    • 该语句只执行结构中的一个代码块,它依次检查每个条件测试,直到遇到通过了的条件测试
    • 并不要求if-elif结构后面必须有else代码块

    5.3.6 测试多个条件

    • 当需要检查你关系的所有条件时,应使用一些列不包含elif和else代码块的简单if语句

    5.4 使用if语句处理列表

    • 检查特殊元素,先用for语句遍历,再用if语句判断元素具体情况
    • 确定列表不为空,先用if语句判断列表是否为空,再if代码块中执行for循环,否则执行else代码块
    • 使用多个列表,检查列表1中的元素是否在列表2中
    list_1 = [1,2,3,4,5]
    list_2 = [1,2,5,6,7]
    for i in list_1:
        if i in list_2:
            print("yes")
        else:
            print("no")
    

    第6章 字典

    6.2 使用字典

    • 用放在花括号{}中的一些列键-值对表示,如student = {"name":"paul","age":28}
    • 可以利用字典的键名访问相关联的值,如student['name']
    • 指定字典名、用方括号括起来的键和相关联的值,添加键-值对,如student[score] = 100
    • 注意,键-值对的排列顺序与添加顺序不同,Python不关心键-值对的添加顺序,而只关心键和值之间的关联关系
    • 使用字典来存储用户提供的数据或在编写自动生成大量键-值对的代码时,通常都需要先定义一个空字典
    • 要修改字典的值,直接用原字典名和键名来重新赋值,如student[score] = 99
    • 要删除键-值对,可以使用del语句,但必须指定字典名和要删除的键,如del student["name"],删除的键-值对永远消失
    • 使用较长的列表或字典时,使用以下格式设置方式:
    student_score = {
        "a":80,
        "b":90,
        "c":100,
        }
    

    6.3 遍历字典

    • 有多种遍历字典的方式:可以遍历字典的所有键-值对,键或值
    • ①遍历所有的键-值对,用for key,value in student_score.items():,注意,即便遍历字典时,键-值对的返回顺序也与存储顺序不同
    • ②遍历字典中的所有键,用for key in student_score.keys():,遍历字典时会默认遍历所有键,将代码改为for key in student_score:输出将不变
    • ③按顺序遍历字典中的所有键,用函数sorted()for name in sorted(student_score.keys()):
    • ④遍历字典中的所有值,用for value in student_score.values():,该方法没有考虑值是否重复,为剔除重复项,可使用集合set,它类似与列表,但每个元素都必须是独一无二的for name in set(student_score.values()):

    6.4 嵌套

    • 将一系列字典存储在列表中,或将列表作为值存储在字典中,也可以同种类型存储
    aliens = []
    #创建30个绿色外星人
    for alien_number in range(30):
        new_alien = {"color":"green","points":"5","speed":"slow"}
        aliens,append(new_alien)
        
    #修改前3个外星人
    for alien in aliens[:3]:
        if alien["color"] == "green":
            alien["color"] = "yellow"
            alien["points"] = 10
            alien["speed"] = "medium"
        elif alien["color"] == "yellow":
            alien["color"] = "red"
            alien["points"] = 15
            alien["speed"] = "fast"
    
    • 在字典中存储列表,这种情况下遍历该字典的for循环中,需要再使用一个for循环来遍历
    for name,languages in favorite_languages.items():
        print("
    " + name.title() + "'s favorite languages are:")
            for language in languages:
                print("	" + language.title())
    
    • 在字典中存储字典,尽量让每个键包含字典结构都相同,否则for循环内部的代码将更为复杂

    第7章 用户输入和while循环

    7.1 函数input()的工作原理

    • 创建多行字符串的方式
    prompt = "If you tell us who you are, we can personalize the message you see ."
    prompt += "
    what is your frist name?"
    name = input(prompt)
    print("
    Hello," + name + "!")
    
    • 使用函数input()时,将用户输入解读为字符串,可用函数int()将字符串转化为数值
    • 求模运算符%,指出余数是多少

    7.2 while循环

    • 学会使用标志控制程序运行:在要求很多条件都满足才继续运行的程序中,可定义一个变量,用于判断整个程序是否处于活动状态。这个变量被称为标志,充当程序的交通信号灯,可让程序在表示为True时继续运行,并在任何事件导致标志的值为False时让程序停止运行。
    active = True
    while active:
        message = input()
        if message == "quit"
            active = False
        else:
            print(message)
    
    • 使用break退出循环
    • 使用continue返回到循环开头,并根据条件测试结果决定是否继续执行循环,不像break语句那样不再执行余下代码并退出整个循环
    • 避免无限循环,确认程序至少有一个这样的地方能让循环条件为False或让break语句得以执行

    7.3 使用while循环来处理列表和字典

    • for循环是一种遍历列表的有效方式,但在for循环中不应修改列表,否则将导致Python难以跟踪其中的元素,要在遍历列表的同时对其进行修改,可使用while循环
    #先创建一个待验证用户列表和一个用于存储已验证用户的空列表
    unconfirmed_user = ["a","b","c"]
    confirm_users = []
    #验证每个用户,直到没有未验证用户为止,将每个验证过的用户移到已验证用户列表中
    while unconfirmed_user:
        current_user = unconfirmed.pop()
        print("Verifying user" + current_user.title())
        confirmed_user.append(current.user)
    #显示所有已验证的用户
    print("
    The following users have been confirmed:")
    for confirmed_user in confirmed_users:
        print(confirmed_user.title())
    
    • 删除包含特定值的所有列表元素
    while "cat" in pets:
        pets.remove("cat")
    
    • 使用用户输入来填充字典
    responses = {}
    #设置一个标志,指出调查问卷是否继续
    polling_active = True
    while polling_active:
        #提示输入被调查者的名字和回答
        name = input("
    What is your name?")
        response = input("Which moutain would you like to climb someday")
        #将答卷存储在字典中
        responses[name] = response
        #看看是否还有人要参加调查
        repeat = input("Would you like to let another person respond?(Y/N)")
        if repeat == "N":
            polling_active = False
    #调查结束,显示调查结果
    print(
    ---Poll Result---)
    for name,response in responses.items():
        print(name + "would like to climb " + response + ".")
    

    第8章 函数

    8.1 向函数传递信息

    • 向函数传递信息
    def greet_user(username):
        print("Hello," + username.title() + "!")
    greet_user("Jesse")
    
    • 如上述变量username是一个形参,是函数完成其工作所需的一项信息;值Jesse是一个实参,是调用函数时传递给函数的具体信息

    8.2 传递实参

    • 向函数传递实参的方式很多,可是使用位置参数,这要求实参的顺序与形参的顺序相同;也可以使用关键字实参,其中每个实参都有变量名和值组成;还可以使用列表和字典。

      1、位置参数

      调用函数时,将函数调用中的每个实参都关联到函数定义中的一个形参,这种关联方是被称为位置参数。优点是可以多次调用函数,但要注意实参的顺序与函数定义中形参的顺序一致。

      2、关键字实参

      是传递给函数的名称-值对,向函数传递时不会混淆,因此无需考虑函数调用中的实参顺序。

      3、默认值

      编写函数时,可以给每个形参指定默认值。使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的形参,这样才能正确地解读位置实参。

    8.3 返回值

    在函数中使用return语句将值返回到调用函数的代码行,返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

    • 调用返回值的函数时,需要提供一个变量,用于存储返回的值
    • 使用默认值让实参变成可选的(末尾添加可选形参)
    def get_formatted_name(first_name,last_name,middle_name=“ ”):
        if middle_name:         #python将非空字符解读为True
            full_name = first_name + " " +middle_name + " " + last_name 
        else:
            full_name = first_name + " " + last_name
        return full_name.title()
    musician = get_formatted_name("jimi","hendrix")
    print(musician)
    

    8.4 向函数传递列表

    • 将列表传递给函数后,函数就可以对其进行修改,并且函数对这个列表所做的任何修改都是永久性的,这样能够高效地处理大量的数据。
    • 使用函数与未使用函数的代码相比,组织更为有序,完成大部分工作的代码都移到了函数中,让主程序更容易理解。
    • 禁止函数修改列表的方法,可向函数传递列表的副本而不是原件funcition_name(list_name[:]) #用切片的方法创建列表的副本,尽量用原始列表传递给函数,让函数使用现成列表可避免花时间和内存创建副本,提高效率,尤其是在处理大型列表时。

    8.5 传递任意数量的实参

    • 利用带星号的形参如*toppings,创建一个名为toppings空元祖,并将所有值都封装到这个元组中。def make_pizza(*toppings):
    • 利用带双星号的形参如**user_info,创建一个名为user_info空字典,将任意数量的关键字参数封装到这个字典中。
    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
    
    • 当结合使用位置实数和任意数量实参时,python先匹位置实参,任意形参,任意关键字实参,默认形参。

    8.6 将函数存储在模块中

    • 函数的优点之一是,可以将代码块与主程序分离,给函数指定描述性名称,让主程序更易于理解。
    • 导入模块的方法

    (1)导入整个模块
    编写一条import并在其中指定模块名import pizza,模块的扩展名为.py的文件,此时可以使用pizza中定义的所有函数,调用函数时需要使用句点pizza.make_pizza()

    (2)导入特定的函数
    from module_name import function_01,function_02,from pizza import make_pizza调用函数时无需使用句点。

    (3)使用关键字as给函数指定别名
    from module_name import function_name as fn

    (4)使用关键字as给模块指定别名
    import module_name as mn

    (5)导入模块中的所有函数
    from module_name import *

    • 调用函数时无需使用句点,但最好不要采用这种导入方法,可能遇到多个名称相同的函数或变量,进而覆盖函数。

    8.7 函数编写指南

    • 函数指定描述性名称,模块命名也同样。
    • 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。
    • 给形参指定默认值时,等号两边不要有空格,对于函数调用中的关键字实参,也应该遵循这种约定。
    • 如果函数形参很多,可在函数定义中输入左括号后按回车,下行写,如:
    def function_name(
            parameter_0,parameter_2,parameter_3,
            parameter_4,parameter_5,parameter_6)
        function body.....
    

    第9章 类

    9.1 创建和使用类

    • 定义一大类对象一般都有通用行为,基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性
    • 首字母大写的名称是指类

    (1)方法__inif__()

    • 类中的函数称为方法
    • Python调用__inif__()方法来创建某个实例时,将自动传入实参self,每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
    • self为前缀的变量都可以供类中的所有方法使用,可以通过类的任何实例来访问这些变量。通过实例访问的变量称为属性。

    9.1.2 根据类创建实例

    (1)访问实例的属性

    • 使用句点表示法:my_dog.name

    (2)调用方法

    • 指定实例名称和要调用的方法:my_dog.sit()

    9.2 使用类和实例

    (1)给属性指定默认值

    • 类中的每个属性都必须有初始值,有些情况下,可以在方法__init__()内指定这种初始值;如果这样做了,就无需包含为它提供初始值的形参。
    class Car():
    
        def __init__(self,make,model,year):
            """初始化描述汽车的属性 """
            self.make = make
            self.model = model
            self.year = year
            self.odometer_reading = 0
        
    my_new_car = Car('audi','a4','2016')
    

    (2)修改属性的值
    可以用三种不同的方法修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方法进行递增(增加特定的值)

    • 方法一:
      my_new_car.odometer_reading = 23
    • 方法二,编写对属性进行更新的方法,好处是无需直接访问属性,而可将值传递给一个方法,由它在内进行更新:
    class Car():
        --snip--
        
        def update_odometer(self,mileage):
            """将里程表读数设置为指定值,并不允许里程表往回拨"""
            if mileage >= self.odometer_reading:
                self.odometer_reading = mileage
            else:
                print("You can't roll back an odometer!")
    
    • 方法三:
    def increment_odometer(self.miles):
        """将里程表读数增加指定的量"""
        self.odometer_reading += miles
    

    9.3 继承

    一个类继承另外一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

    (1)子类的方法__init__()

    class ElectricCar(Car):
        """电动汽车的独特之处"""
        
        def __init__(self,make,model,year):
            """初始化父类的属性"""
            super().__init__(self,make,model,year)
    
    • 定义子类时,必须在括号内指定父类的名称
    • super()函数能将父类和子类关联起来,父类也称为超类,此处super()等价于super(ElectricCar,self)

    (2)给子类定义属性和方法

    • 在方法__init__()中添加

    (3)重写父类的方法

    • 在子类中定义一个与要重写父类方法同名的方法,Python将不会考虑父类的方法,而只关注在子类定义的相应方法。

    (4)将实例用作属性

    • 当类中的属性和方法越来越多,可能需要将类的一部分作为一个独立的类提取出来,并将Battery这个独立类的实例作为另一个类ElectricCar的属性。
    class Battery():
    
        def __init__(self,battery_size=70):
            self.battery_size = battery_size
    
    class ElectricCar(Car):
    
        def __init__(self,make,model,year):
            """初始化父类的属性,再初始化电动汽车特有的属性"""
            super()__init__(make,model,year)
            self.battery = Battery()
    

    9.4 导入类

    Python允许将类储存在模块中,然后在主程序中导入所需的模块。

    • 导入单个类
      from car import Car使主程序文件变得整洁而易于阅读
    • 从一个模块中导入多个类
      from car import Car,ElectricCar
    • 导入整个模块
      import Car
    • 导入模块中的所有类(不推荐)
      from module_name import *这种方式首先没有明确指出模使用了模块中的哪些类,其次容易重名引发报错
    • 在一个模块中导入另一个模块
      可能会发现一个模块中的类依赖于另外一个模块中的类,这种情况下,可在前一个模块中导入必要的类

    9.5 类编码风格

    • 类名采用驼峰命名法,即类名的每个单词的首字母都大写,而不使用下划线
    • 实例名和模块名使用小写格式,并且单词之间加上下划线
    • 对于每个类,都应紧跟在定义后包含一个文档字符串
    • 利用空行来组织代码,在类中,使用一个空行来分隔方法;在模块中,使用两个空行来分隔类

    第10章 文件和异常

    10.1 从文件中读取数据

    • 要使用文本文件中的信息,首先需要将信息读取到内存中。
    with open("pi_digits.txt") as file_object:   #函数open()返回一个表示文件的对象,有关键字with在,就不再需要访问文件后自动将其关闭
        contents = file_object.read()            #方法read()读取文件的全部内容
        print(contents)
    

    10.2文件路径

    • 上述将文件名传递给函数open()时,Python将在当前执行的文件(即.py程序文件)所在的目录中查找文件。
    • 在程序文件夹的其他子文件夹中,可以使用相对文件路径来打开文件夹中的文件,该位置是相对于当前运行的程序所在目录的。在Linux和OS X中,文件路径使用斜杠(/)在Windows系统中,文件路径使用反斜杠(),如:`with open('text_filesfilename.txt') as file_objetc:
    • 也可以使用绝对文件路径,通常比相对路径更长,可以存储在一个变量中,便于使用。
    • 由于反斜杠在Python中被视为转义标记,为在Windows中确保万无一失,应以原始字符串的方式指定路径,即在开头的单引号上加上r

    (1)逐行读取
    for line in file_object:

    (2)创建一个包含文件各行内容的列表

    • 使用关键字with时,open()返回的文件对象只在with代码块内使用,如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表,并在with代码块外使用该列表。
    with ope(filename) as file_object:
        lines = file_object.readlines()     #方法readlines()从文件中读取每一行,并将其存储在一个列表中
    

    10.3 写入文件

    • 在调用open()提供另一个实参with open(filename,"w") as file_object:,w表示以写入模式打开文件,如果指定文件已存在,将在返回文件对象前清空该文件;r表示以读取模式打开文件,忽略实参时默认;a表示以附加模式打开文件,如果指定的文件不存在,将创建一个空文件。
    • Python只能将字符串写入文本文件

    10.4 异常

    • 异常使用try-except-else代码块处理。
    • 好处:使异常避免崩溃,提供程序抵御错误的能力,避免用户看到traceback;避免恶意用户看到程序的文件名称和部分不能正确运行的代码。
    print("Give me two numbers,and I'll divide them.")
    print("Enter 'q' to quit.)
    
    while True:
        first_number = input("
    First number:")
        if first_number == "q":
            break
        second_number = input("
    Second number:")
        try:
            answer = int(first_number) / int(second_number)
        except ZeroDivisionError:
            print("You can't divide by 0!")
        else:
            print(answer)
    

    10.4.1 分析文本

    • 方法split()以空格为分隔符将字符串拆分成多个部分,并将这些部分都存储到一个列表中。
    >>> title = "Alice in Wonderland"
    >>> title.split()
    ['Alice','in','Wonderland']
    

    10.5 存储数据

    • 使用模块json(JavaScript Object Notation)来存储数据,JSON格式存储的数据可以与使用其他编程语言的人分享。

    10.5.1 使用json.dump()json.load()

    • 函数json.dump()接受两个实参:要存储的数据以及可用存储数据的文件对象,通常使用文件扩展名.json来指出文件存储的数据为JSON格式。
    import json
    
    numbers = [1,2,3,4,5]            #如何用`json.dump()`来存储数字列表
    
    filename = "numbers.json"
    with open(filename,"w") as f_obj:
        json_dump(numbers,f_obj)
        new_numbers = json.load(f_obj)   #使用`json.load()`将这个列表读取到内存中
    

    10.5.2 代码重构

    • 例子:保存和读取用户生成的数据remember_me.py
    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 + "!")
    
    • 上述代码尽快能够正确运行,但仍然可以进一步将代码划分为一系列完成具体工作的函数,这样的改进过程称为重构。
    • 重构让代码更清晰、更易于理解、更容易扩展,让每个函数都执行单一而清晰的额任务,好好体会重构后的代码:
    import json
    
    def get_stored_username():
        '''如果存储了用户名,就获取它'''
        filename = "username.json"
        try:
            with open(filename) as f_obj:
                username = json.load(f_obj)
        except FileNotFoundError:
            return None
        else:
            return username     
            #函数要么返回None,要么返回预期的值,易于使用函数的返回值做简单测试
    
    def 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 username
    
    def 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()
    

    第11章 测试代码

    • 主要使用标准库中的unittest模块来测试代码(函数和类)

    11.1 测试函数

    • 单元测试:用于核实函数的某个方面是否符合要求
    • 测试用例:是一组单元测试,用于一起核实函数在各种情况下的行为是否都符合要求
    • 全覆盖式测试:包含一整套单元测试,涵盖了各种可能得函数使用方式

    test_name_function.py

    import unittest
    from name_function import get_formatted_name   #导入模块unittest以及要测试的函数,再创建一个继承unittest.TestCase的类
    
    class NamesTestCase(unittest.TestCase):      #创建一个继承unittest.TestCase的类,用于包含一系列针对get_formatted_name()的单元测试
        """测试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()    
    #让Python运行文件中的测试,所有test_打头的方法都将自动运行,因此被测试的方法名必须以test_打头
    
    • 运行测试用例时,每完成一个单元测试,Python都打印一个字符:测试通过打印一个句点,测试引发错误打印一个E,测试导致断言失败打印一个F
    • 测试未通过时,不要修改测试,而应修复导致测试不能通过的代码

    11.2 测试类

    • unittest.TestCase类中提供了各种断言方法,常用的6种:
    方法 用途
    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中
    • unittest.TestCase类包含方法setUp(),只需创建对象一次,就能在每个测试方法中使用它们,Python将先运行它,再运行各个以test_打头的方法
    import unittest
    from survey 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.response[0],self.my_survey.responses)
        
        def test_store_three_response(self):
            """测试三个答案会被妥善地存储"""
            for response in self.responses:
                self.my_survey.store_response(response)
            for resopnse in self.response:
                self.assertIn(response,self.my_survey.responses)
    
    unittest.main()
    
  • 相关阅读:
    面试题: !=!=未看12 略多 sql语句练习 非常 有用
    面试题--阿里
    LeetCode--Count Primes
    (转载)协方差的意义
    LeetCode--Isomorphic Strings
    LeetCode--Reverse Linked List(Java)
    JDBC连接数据库的过程
    (转载)Java中如何遍历Map对象的4种方法
    Ubuntu下Eclipse中运行Hadoop程序的参数问题
    Hadoop上配置Hbase数据库
  • 原文地址:https://www.cnblogs.com/luowei2018/p/10146051.html
Copyright © 2011-2022 走看看