Python语言基础教程(下)4.0

news2024/9/21 20:06:21

在这里插## 标题入图片描述

> 						大家好,我是程序员小羊!

✨博客主页: https://blog.csdn.net/m0_63815035?type=blog

💗《博客内容》:.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识
📢博客专栏: https://blog.csdn.net/m0_63815035/category_11954877.html
📢欢迎点赞 👍 收藏 ⭐留言 📝
📢本文为学习笔记资料,如有侵权,请联系我删除,疏漏之处还请指正🙉
📢大厦之成,非一木之材也;大海之阔,非一流之归也✨

在这里插入图片描述

前言

本文是黑马Python4.0编程学习笔记,里面有相关的知识点还是重要的,期待大家的关注!!!

这里写目录标题

  • 前言
  • DAY--------------------------------------------07 (面向对象)
  • 对象
  • 面向对象设计的基础
  • class关键字
  • 对象
  • self参数的作用
  • init方法
  • del方法
  • str方法
  • 类设计实例演示-计算器
  • DAY--------------------------------------------08 (面向对象)
  • 面向对象三大特性
  • 封装
  • 继承
  • 专业术语
  • 多级继承
  • 方法的重写
    • 覆盖父类方法
    • 扩展父类方法
  • 父类的私有成员不会继承给子类
  • 多态
  • 类属性
  • 类方法
    • 课堂练习-类属性和类方法
    • 在普通方法中使用类属性和类方法
  • 静态方法
    • 静态方式使用场景
  • object类(了解即可)
  • DAY--------------------------------------------09 (文件)
  • 读取第一个文件内容
  • 写第一个文件内容
  • 追加写文件内容
  • 总结打开文件的方式
  • 打开文件的时候,指定字符集
  • 课堂练习-修改文件内容
  • 复制文件
  • 课堂练习-合并文件
  • 按行读取文件内容
  • 课堂练习-读取文件偶数行
  • readlines
  • 课堂练习-计算文件中最大数字与最小数字的差
  • with open语法
  • json文件
  • 读取json文件的方法
  • 操作json文件常见错误
    • 错误1:json格式错误
    • 错误2:扩展名不是json,是其他的
    • 错误3:自己创建了一个文件名叫json.py
  • 写json文件
  • 课堂练习-修改json文件内容
  • 在pycharm中安装课程需要的包-演示
  • DAY--------------------------------------------10 (UnitTest)
  • UnitTest介绍
  • TestCase
  • TestSuite
  • TextTestRunner
  • TestLoader
  • TestSuite和TestLoader的使用区别
  • 小结
  • Fixture
    • 方法级
    • 类级
    • 模块级
    • fixture小结
  • 断言
    • unittest断言
  • 参数化
    • 测试用例中使用参数化的场景
  • 手工安装py包的过程
  • 参数化
  • 跳过(了解即可)
  • 通过TextTestRunner生成测试报告
  • HTML测试报告
  • DAY--------------------------------------------11 (异常)
  • 异常
    • 捕获异常
    • 捕捉不同类型异常
    • 没有异常发生执行的代码
    • 主动抛出异常
    • 捕捉主动抛出的异常
  • 模块
    • from import导入指定内容
    • `__name__`属性
    • 创建步骤的演示
    • 导入包中指定函数
    • 课堂练习-my_pack1包

DAY--------------------------------------------07 (面向对象)

  • 类是一个图纸,模板
  • 类不能直接使用, 相当于设计飞机的时候画的图纸
  • 类中行为----方法
  • 类的特性----属性

对象

  • 根据类制造出来,可以直接使用的
  • 一个类可以制造多个对象
  • 每个对象的属性的值可能有所不同
  • 一定先有类,然后才有对象

面向对象设计的基础

  • 面向对象编程首先要设计类

  • 类的三个要素

    • 类名
    • 属性
      • 类中的变量—属性
    • 方法
      • 类中的函数—方法
  • 设计一个小猫类

    • 类名cat
    • 属性
      • name(名字)
      • color(颜色)
      • height(身高)
      • weight(体重)
      • sex(性别)
    • 方法
      • eat(吃)
      • drink(喝)
      • sleep(睡)

class关键字

  • 定义一个类
  • 语法
class 类名:
    def 方法名(self, 参数1, 参数2, ......):
        pass
class cat:
    def eat(self):
        print("猫吃饭")
    def drink(self):
        print("猫喝水")



对象

  • 类中的方法不能直接调用
  • 把类实例化为对象后,通过对象调用方法
  • 实例
    • 通过类创建的对象, 叫类的实例
  • 实例化
    • 创建对象的动作, 叫实例化
  • 语法
对象名 = 类名(参数列表)
# 对象创建后通过对象名.方法名(参数),调用方法
对象名.方法1()
class cat:  # 定义了一个类cat,这个类不能直接使用
    def eat(self):  # 第一个参数必须是self
        print("猫吃饭")
    def drink(self):
        print("猫喝水")

c1 = cat()   # 根据类cat, 创建了一个对象c1, 对象名类似于变量名
c1.eat()  # 调用的时候,不需要提供self对应的实参
c1.drink()  # 调用对象的方法
# 方法只能通过对象调用,不能通过类直接调用
# c1就是类cat的实例
# c1 = cat() 这个动作就叫实例化
c2 = cat()   # 实例化, 实例化的结果是cat类有一个对象叫c2
# c2是类cat的实例

self参数的作用

  • self可以在方法内部定义和使用属性
  • self可以在方法内部嵌套调用其他方法
  • 在类的外部,是不能使用self的
  • 在类的外部调用方法
    • 对象名.方法名
  • 在类的外部使用属性
    • 对象名.属性名
class cat:  # 定义了一个类cat,这个类不能直接使用
    def set_name(self):
        self.name = "tom"  # 定义了一个属性,名叫name,值是tom

    def eat(self):  # 第一个参数必须是self
        print("%s吃饭" % self.name) # 这里在使用name属性
    def drink(self):
        print("%s喝水" % self.name) # 这里在使用name属性

    def demo(self):  # 这个方法只是为了举例,在类的内部,方法嵌套调用
        self.eat()
        self.drink()

c = cat()
c.set_name()
c.drink()
c.eat()
c.name = "张三"
c.drink()
c.eat()
c.demo()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class dog:
    def set_name(self, name):
        self.name = name
    def show_name(self):
        print(self.name)

d = dog()
d.set_name("旺财")
d.show_name()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

init方法

  • __init__注意名字,前面两个下划线,后面两个下划线
  • 当创建对象的时候,也就是实例化对象的时候,init自动调用
class cat:
    def __init__(self):
        print("cat被创建了")
    def eat(self):
        print("小猫爱吃鱼")

c = cat()  # 实例化对象的时候,init方法自动调用
c.eat()  # 必须明确的通过代码调用普通方法
  • init方法的作用
    • 定义类中的属性
    • 同时通过init方法的参数为属性赋值
    • init方法一旦有形参,对象实例化的时候就必须提供实参
    • 为了避免实例化的时候必须提供实参,init的形参总是有缺省值
# class cat:  # 不在普通方法中定义属性
#     def set_name(self, name):
#         self.name = name
#     def show_name(self):
#         print(self.name)
class cat:
    def __init__(self, name = "tom"):
        self.name = name
    def set_name(self, name):
        self.name = name
    def show_name(self):
        print(self.name)

c = cat("张三")  # init自动已经调用了,所以name属性已经有了
c.show_name()

在这里插入图片描述

  • 如果init有形参,实例化对象的时候,必须提供实参
class cat:
    def __init__(self, name):
        pass

c = cat("tom")  # 如果init有形参,那么实例化对象的时候,必须提供实参
  • 一个完整的cat说明
class cat:
    def __init__(self, name = "tom", color = "red"):
        self.name = name
        self.color = color

    def show_name(self):
        print(self.name)

    def show_color(self):
        print(self.color)

    def show(self):
        self.show_name()
        self.show_color()

c1 = cat("小猫", "white")
c1.show_name()
c1.show_color()
c2 = cat("大猫", "black")
c2.show_name()
c2.show_color()
c3 = cat()
c4 = cat("懒猫")

  • 课堂练习-car类的设计
# 汽车car       要区分属性和方法,在init方法中为每个属性定义默认值
# 属性
# luntai(轮胎)
# yanse(颜色)
# chuanghu(窗户)
# xinghao(型号)
# 方法
# guadang(挂挡)
# qianjin(前进)
# houtui(后退)
# wurenjiashi(无人驾驶)
# shache(刹车)
# jiayou(加油)

class car:
    def __init__(self, luntai="轮胎", yanse="白色", chuanghu="黑窗户", xinghao="大众"):
        self.luntai = luntai
        self.yanse = yanse
        self.chuanghu = chuanghu
        self.xinghao = xinghao

    def guadang(self, a = "前进"):
        self.jiayou()
        if a == "前进":
            self.qianjin()
        elif a == "后退":
            self.houtui()
        else:
            print("档不对")

    def qianjin(self):
        print("%s在前进" % self.xinghao)
    def houtui(self):
        print("%s在后退" % self.xinghao)
    def wurenjiashi(self):
        print("无人驾驶")
    def shache(self):
        print("刹车")
    def jiayou(self):
        print("加油")

c = car()
# c.qianjin()
c.guadang("前进")

c1 = car(xinghao="奔驰")
c1.guadang("后退")

del方法

  • 当对象在内存中销毁的时候,自动调用del方法
  • del方法只有一个参数self
class cat:
    def __init__(self, name = "tom"):
        self.name = name

    def show_name(self):
        print(self.name)

    def __del__(self):
        print("%s销毁了" % self.name)

c = cat()  # c是个对象,同时也是一个变量
c.show_name()  # 这里显示了tom

如果对象是局部的,那么函数执行完毕,自动调用对象的del方法

如果对象是全局的,那么程序执行完毕,自动调用对象的del方法

class cat:
    def __init__(self, name = "tom"):
        self.name = name

    def show_name(self):
        print(self.name)

    def __del__(self):
        print("%s销毁了" % self.name)

def my_test1():
    c1 = cat("小猫")
    c1.show_name()

my_test1()   # 程序的第一条执行语句
c = cat()  # c是个对象,同时也是一个变量
c.show_name()  # 这里显示了tom
  • __init__不要写成__int__

  • __del__对象在内存中销毁的时候自动调用del

    • 不要理解成调用del是把对象从内存中删除了
    • 对象即使没有del,同样会被销毁
    • 当对象从内存中销毁的时候,有机会能执行一些代码
  • 设计方法的惯例

class cat:
    def __init__(self, name = "tom"):
        self.name = name

    # 不想写show_name方法, 只是想把name返回给调用者
    def get_name(self):   # 设计方法管理,得到属性值get_属性名
        return self.name

    def set_name(self, name):  # set_属性名(self, 形参)
        self.name = name

    def show_name(self):  # 在方法中显示属性的值一般show_属性名
        print(self.name)

c = cat()
print(c.get_name())
print(c.show_name()) # 没有return语句的方法或者函数,不要放到print
c1 = cat("小猫")
c1.set_name("加菲猫")
print(c1.get_name())

  • 课堂练习-设计小狗类
# 有一个dog类,有属性name和age
# 提供设置,得到,显示name和age属性的方法
class dog:
    def __init__(self, name = '二哈', age = 2):
        self.name = name
        self.age = age

    def set_name(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def show_name(self):
        print(self.name)

    def set_age(self, age):
        self.age = age

    def get_age(self):
        return self.age

    def show_age(self):
        print(self.age)

d = dog("比熊", 3)  # 实例化的时候设置属性的值
print(d.get_name())
d.set_name("黑背") # 实例化以后再设置属性值
print(d.get_name())
d.show_name()

str方法

  • __str__
    • 只有self,没有其他参数
    • 必须有return return必须返回一个字符串
  • str方法的作用
    • 当把一个带有str方法的对象放到print里面,print函数会显示str方法return返回的字符串
  • 如果类没有str方法,那么类实例化的对象放到print里面显示的是对象的内存地址
class cat:
    def __init__(self):
        pass

c = cat()
print(c)  # 当把对象直接放到print里面,实现的是对象在内存的地址编号
# 有时候,我们希望print能显示我们想显示的内容

# 假设,自己设计一个对象,放到print里面,显示对象的name属性值
class demo:
    def __init__(self, name = "demo"):
        self.name = name

    def __str__(self):
        return self.name

d = demo()
print(d)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class dog:
    def __str__(self):
        return "这是一个小狗类对象"

d = dog()
print(d)

类设计实例演示-计算器

class calc:
    def __init__(self, oper = "+"):
        self.oper = oper

    def calc(self, a, b):
        if self.oper == "+":
            return a + b
        elif self.oper == "-":
            return a - b
        elif self.oper == "*":
            return a * b
        elif self.oper == "/":
            if b != 0:
                return a / b
            else:
                return None
        else:
            return None

c = calc()
print(c.calc(3, 4))

d = calc("*")
print(d.calc(3, 4))

e = calc("/")
print(e.calc(3, 0))

f = calc("sdfsd")
print(f.calc(4, 5))

DAY--------------------------------------------08 (面向对象)

面向对象三大特性

  • 封装
  • 继承
  • 多态

封装

  • 就是把类的属性和方法封装到类的内部,只能在内部使用,不能在类的外部使用
  • 把属性和方法名前面加两个下划线__,这个属性和方法就成为了类的私有属性和方法
class woman:
    def __init__(self):
        self.name = "玛丽"
        self.__weight = 200  # __weigth是一个私有属性

    def __eat(self):   # __eat方法为私有方法
        print("吃的很多")



w = woman()
print(w.name)
# print(w.__weight)  不能在类的外部访问类的私有属性
# w.__eat()   不能在类的外部调用私有方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

class user:
    def __init__(self):
        self.name = "tom"
        self.__passwd = "123456"

    def show_name(self):
        print(self.name)

    def __show_passwd(self):
        print(self.__passwd)

u = user()
u.show_name()
# u.__show_passwd()  类的外部不能访问类的私有属性和方法

继承

  • 类A继承自类B,类A会拥有类B的所有属性和方法
  • 语法
class A:
    pass
class B(A):  # B继承自类A
    pass
class animal:
    def sleep(self):
        print("睡")
    def eat(self):
        print("吃")

class dog(animal):  # 类dog继承自animal类
    def run(self):
        print("跑")

d = dog()   # dog会拥有animal所有属性和方法
d.sleep()
d.eat()
d.run()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

专业术语

  • 子类—派生类

    • dog是animal的子类
    • dog是animal的派生类
  • 父类—基类

    • animal是dog的父类
    • animal是dog基类
  • 继承—派生

    • dog类继承自animal
    • dog类派生自animal
  • 一个父类可以有多个子类继承,每个子类可以有自己特有的方法和属性

class animal:
    def sleep(self):
        print("睡")

    def eat(self):
        print("吃")

class dog(animal):
    def run(self):
        print("跑")

class fish(animal):
    def swimming(self):
        print("游泳")

class bird(animal):
    def fly(self):
        print("飞")

针对animal类,dog,fish和bird类是说明

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多级继承

  • 类C继承自类B,类B继承自类A
  • 类C就拥有了类B和类A的所有属性和方法
class animal:
    def sleep(self):
        print("睡")

    def eat(self):
        print("吃")

class dog(animal):
    def run(self):
        print("跑")

class erha(dog):
    def kawayi(self):
        print("萌")

e = erha()
e.sleep()
e.eat()
e.run()
e.kawayi()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 课堂练习-多级继承
class animal:
    def sleep(self):
        print("睡")

    def eat(self):
        print("吃")

class dog(animal):
    def run(self):
        print("跑")

class fish(animal):
    def swimming(self):
        print("游泳")

class erha(dog):
    def kawayi(self):
        print("萌")

class cangao(dog):
    def yaoren(self):
        print("咬人")

class shark(fish):
    def chiren(self):
        print("吃人")

s = shark()
s.sleep()
s.eat()
s.swimming()
s.chiren()

c = cangao()
c.sleep()
c.eat()
c.run()
c.yaoren()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方法的重写

  • 父类的方法不能满足子类的需求
  • 方法重写有两种方式
    • 覆盖父类方法
    • 扩展父类方法

覆盖父类方法

  • 子类中出现和父类相同的方法,那么在子类中相同方法会把父类的方法覆盖
class animal:
    def sleep(self):
        print("睡")

    def eat(self):
        print("吃")

class dog(animal):
    def eat(self):  # 出现和父类同名方法,在子类dog中,就没有父类的eat方法了
        print("吃肉")

d = dog()
d.sleep()
d.eat()  # 由于覆盖了父类的eat方法,,所以这里调用的是dog类的eat方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

扩展父类方法

  • 如果父类的方法不能完全满足子类需求, 子类可以在父类方法基础上增加功能
  • 语法
1.在子类中实现和父类同名方法
2.在子类的同名方法中用super().父类同名方法 来调用父类的方法
class animal:
    def sleep(self):
        print("睡")

    def eat(self):
        print("吃")

class dog(animal):
    def sleep(self):
        super().sleep() # 在子类方法中调用父类的sleep方法
        print("睡得更多")

d = dog()
d.sleep() # 扩展了父类的sleep,所以既执行了父类的sleep,又增加了功能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

父类的私有成员不会继承给子类

  • 父类中所有的私有方法和私有属性归父类特有,子类不能继承
class animal:
    def sleep(self):
        print("睡")

    def __eat(self):  # 私有成员不会被子类继承
        print("吃")

class dog(animal): # 在dog类里面,没有__eat方法
    pass

d = dog()
d.sleep()
# d.__eat()  # 这里的代码会出错

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 课堂练习-father类和继承
class father:
    def __init__(self):
        self.__name = "张三"
        self.house = "别墅"
    def eat(self):
        print("吃")
    def sleep(self):
        print("睡")
    def __edu_back(self):
        print("本科")

class son(father):  # son拥有father所有的方法和属性
    def show_eat(self):
        self.eat()    # eat是继承自father的,但也是son自己的

    def show_sleep(self):
        self.sleep()

    def show_house(self):
        print(self.house) # house是一个属性,不能调用,要用print

s = son()
s.show_eat()
s.show_sleep()
s.show_house()

# father有两个属性,三个方法
# son继承了father一个属性,两个方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多态

  • 不同的子类,调用相同的父类方法,产生不同的结果
  • 多态的前提,不同的子类来自相同的一个父类,子类会覆盖父类的方法
class animal:
    def food(self):
        pass
    def eat(self):
        self.food()

class dog(animal):
    def food(self):
        print("吃肉")

class cattle(animal):
    def food(self):
        print("吃草")

d = dog()
d.eat()
c = cattle()
c.eat()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

类属性

  • 定义在类里面,方法外面,定义的时候不需要self关键字,语法类似于定义普通变量
  • 不需要把类实例化为对象,直接通过类名.属性名 使用
class dog:
    name = "二哈"   # 如果在这个位置定义的变量,就是类属性
    def __init__(self):
        pass

print(dog.name)  # 显示类属性的值
dog.name = "狼狗"  # 修改类属性的值
print(dog.name)

类方法

  • 类方法不需要把类实例化为对象,通过类名.类方法名调用
  • 用@classmethod来修饰的方法,就是类方法
  • 类方法的一个参数是cls(不是self)
  • 在类方法内部如果使用类属性, cls.类属性名
  • 类方法内部不能使用普通属性,也不能调用普通方法
    • 因为类方法不需要对象的,但普通方法和普通属性一定需要通过对象调用
class dog:
    name = "二哈"   # 如果在这个位置定义的变量,就是类属性
    @classmethod
    def set_name(cls, name):
        cls.name = name   # 通过类方法的形参修改类属性name值

    def __init__(self):
        self.age = 20  # 在类方法里面无法访问age

    def demo(self):  # 在类方法中无法调用demo
        print("普通方法")

print(dog.name)  # 显示类属性的值
dog.name = "狼狗"  # 修改类属性的值
print(dog.name)
dog.set_name("比熊")
print(dog.name)

课堂练习-类属性和类方法

class dog:
    name = "小白"
    @classmethod
    def get_name(cls):
        return cls.name

    def __init__(self):
        self.age = 0
    def get_age(self):
        return self.age
# 要把类属性name的值修改为"小小白"
dog.name = "小小白"
# 调用类方法get_name,显示name的值
print(dog.get_name())
# 要把普通属性age的值修改为10
d = dog()
d.age = 10
# 调用普通方法get_age显示age的值
print(d.get_age())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在普通方法中使用类属性和类方法

  • 普通方法中通过类名.类属性或者类名.类方法使用类属性和类方法
class dog:
    name = "小白"
    @classmethod
    def get_name(cls):
        return cls.name

    def demo(self): # 演示如何在普通方法中使用类属性和类方法
        dog.name = "小小白"
        print(dog.get_name())

d = dog()
d.demo()
class dog:
    index = 0   # 定义了一个类属性
    @classmethod
    def count(cls):   # 返回值为类属性index
        return cls.index

    def __init__(self):  # 实例化的时候自动调用init
        dog.index += 1  # 每次实例化的时候类属性index + 1

d1 = dog()
d2 = dog()
d3 = dog()
d4 = dog()
print(dog.count())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

静态方法

  • 在类中通过@staticmethod修饰的方法
  • 静态方法不需要实例化为对象,通过类名.静态方法名 调用
  • 静态方法不能访问类中的其他成员,静态方法就是一个独立与类存在的函数
class dog:
    @staticmethod
    def help():
        print("这是一个静态方法")

dog.help()

静态方式使用场景

  • 当代码量特别大的时候,函数也会特别多,为了避免函数的重名,可以把同名函数放到不同的类里面,做为静态方法
  • 避免由于函数重名带来错误
class dog:
    @staticmethod
    def help():
        print("这是一个静态方法")

class A:
    @staticmethod
    def help():
        print("这是第二个静态方法help")

dog.help()
A.help()

object类(了解即可)

  • 在python3中,如果一个类定义的时候,没有明确的写父类,那么父类就是object
  • object类是python内部自带的
  • 如果是python2,那么如果一个类没有写父类,就是没有父类,不会自动继承自object
class animal:  # 如果定义了一个类,没明确的写父类,那么父类就是object
    def sleep(self):
        print("睡")

# class animal(object):
#     def sleep(self):
#         print("睡")

a = animal()

DAY--------------------------------------------09 (文件)

	# 文件操作步骤
  • 打开文件-open
  • 读写文件
    • 读—把文件的内容读到变量里-read
    • 写—把变量的值写到文件内容里-write
  • 关闭文件-close

读取第一个文件内容

  • 打开文件

    • file = open(要打开文件的路径和文件名, “r”)
    • file是一个变量名,代表文件操作对象
    • open的第一个参数一定要文件存在, 如果文件不存在,会报错
    • "r"意思是用只读方式打开文件
  • 读取文件内容

    • txt = file.read()
    • txt是定义一个变量,代表存放读取到的文件内容
    • file是上一个open返回的文件操作对象
    • read是file对象的一个方法,用来读取文件内容
  • 关闭文件

    • file.close()
    • 文件打开后,一定要记得关闭

# 第一步: 打开文件
file = open(r"C:\file\temp\a.txt", "r")
# 第二步:读取文件内容
txt = file.read()
print(txt)  # 为了显示文件内容
# 第三步:关闭文件
file.close()

写第一个文件内容

  • 打开文件
    • file = open(“要打开的文件路径和文件名”, “w”)
    • 第二个参数w代表用写的方式打开文件
    • 如果用w方法打开文件,文件名不存在,会创建一个新文件,存在的话会覆盖已有文件
  • 写文件
    • file.write(要写入的内容)
  • 关闭文件
    • file.close()
# 第一步:打开文件
file = open(r"c:\file\temp\b.txt", "w")
# 第二步:写内容
file.write("hello python")
# 第三步:关闭文件
file.close()
# 验证程序是否执行成功?看c盘file目录的temp目录下是否生成了文件b.txt
# b.txt文件内容是否为hello python

注意项:如果open第二个参数是"r",打开文件后只能用read读,不能用write写

如果open第二个参数是"w", 打开文件后只能用write写,不能用read读

追加写文件内容

  • 打开文件
    • file = open(“文件路径和文件名”, “a”)
    • "a"当文件不存在的时候创建新文件
    • 当文件存在的时候,在文件后面追加内容
  • 写文件
    • file.write(“要写入文件的内容”)
  • 关闭文件
    • file.close()

file = open(r"c:\file\temp\c.txt", "a")
file.write("hello\n")
file.close()

总结打开文件的方式

  • open函数第二个参数的意思是打开文件的方式
    • r只读
    • w只写
    • a追加写
    • rb用二进制方法打开,只读
    • wb用二进制方法打开,只写
    • ab用二进制方法打开,追加

打开文件的时候,指定字符集

  • 如果文件格式是utf8的,open打开文件的时候需要指定字符集
    • file = open(“文件名”, “r”, encoding=“utf8”)
  • 如果出现以下错误提示,基本就是由于字符集导致的错误
UnicodeDecodeError:
file = open(r"C:\file\teach\05python\day09\3-code\01-open函数.py", "r", encoding="utf8")
txt = file.read()
print(txt)
file.close()

课堂练习-修改文件内容

# 有文件a.txt
# 内容如下:
# 我爱你python, 我爱你
#
# 写代码,把a.txt内容中的python替换为world
#
# 思路,先把a.txt文件内用r方式读出来
# 用字符串的replace方法把python替换为world
# 在用w方式把替换后的内容写回到a.txt里面
file = open(r"c:\file\temp\a.txt", "r")
txt = file.read()
a = txt.replace("python", "world")
file.close()  # 这一步必须关闭
file = open(r"c:\file\temp\a.txt", "w")
file.write(a)
file.close()

复制文件

# 把文件a.txt复制为b.txt
# 思路:把a.txt打开,读取全部内容
# 把b.txt用w方法打开,把内容写入
file = open(r"c:\file\temp\a.txt", "r")
txt = file.read()
file.close()
file = open(r"c:\file\temp\b.txt", "w")
file.write(txt)
file.close()

课堂练习-合并文件

# 有文件a.txt
# 内容如下:
#
# 我爱你python, 我爱你
#
# 有文件b.txt
# 内容如下:
#
# hello
#
# 把文件a.txt和b.txt合并为c.txt
# 思路:把文件a.txt内如读出来放到变量a
# 把文件b.txt内如读出来放到变量b
# 把a + b 结果写入的c.txt中
file = open(r"c:\file\temp\a.txt", "r")
a = file.read()
file.close()
file = open(r"c:\file\temp\b.txt", "r")
b = file.read()
file.close()
file = open(r"c:\file\temp\c.txt", "w")
file.write(a + b)
file.close()

按行读取文件内容

  • readline()按行读取文件内容
  • 由于read一次把文件所有内容都读取到内存中,如果文件特别大,会消耗内存
  • 每调用一次readline,内部的文件指针就会向下一行移动,这样的结果是下次再次调用readline会自动读取下一行
  • readline读取到文件最后,返回""
  • 如果要通过readline来读取文件所有内容
    • 写一些死循环
    • 在循环内部调用readline,读取文件每一行
    • 如果readline返回为"", 终止这个死循环
file = open(r"c:\file\temp\a.txt", "r")
# 在循环开始的时候,不知道文件有多少行,所以也不能决定循环多少次
while True:
    txt = file.readline()
    # 如果readline读取到文件最后末尾,返回""
    if txt == "":
        break
    print(txt, end="")

file.close()

课堂练习-读取文件偶数行

# 有文件a.txt,有很多行,只显示偶数行
# 思路:只读方式打开a.txt,读取所有行,但只显示偶数行
# 做一个循环读取所有行,在循环的时候做一个计数器,每次循环计数器+1
# 可以判断计数器是偶数还是奇数,如果是偶数那么就print

file = open(r"c:\file\temp\a.txt", "r")
index = 1
while True:
    txt = file.readline()
    if txt == "":
        break
    if index % 2 == 0:  # 如果条件成立,代表index为偶数
        print(txt, end="")
    index += 1

file.close()

readlines

  • 一下读取文件所有行,返回一个列表,列表中的一个成员就是文件中的一行, 文件有多少行,列表就有多少成员
file = open(r"c:\file\temp\a.txt", "r")
list1 = file.readlines()
for n in list1:
    print(n, end="")
file.close()

课堂练习-计算文件中最大数字与最小数字的差

# 有个文件a.txt,内容每一行是一个整数,最大值和最小值的差
# 思路:
# 把文件每一行 做为list的每个成员(文件的每一行是字符串)
# 只有max(list) - min (list)
#
# 先做一个空的list
# 循环读每行,把每行用int转化为整数,append到空的list里面
# 循环读完后,就可以max(list) - min(list)
file = open(r"c:\file\temp\a.txt", "r")
list1 = []
while True:
    txt = file.readline()
    if txt == "":
        break
    list1.append(int(txt))
file.close()
print(max(list1) - min(list1))
  • 字符串比较大小的原理
list1 = [2, 12, 5]
list2 = ['2', '12', '5']
print(max(list1), min(list1))
print(max(list2), min(list2))
# 如果长得像数字的字符串比较大小,比较原理是先比较字符串的一个字符

with open语法

  • 这个语法传统的file = open的一种简化语法, 不需要明确的调用close关闭文件
# file = open(r"c:\file\temp\a.txt", "r")
# txt = file.read()
# print(txt)
# file.close()
# 对等代码
with open(r"c:\file\temp\a.txt", "r") as file:
    txt = file.read()
    print(txt)

json文件

  • 一般是定义数据使用的
  • 在互联网传递数据的时候,很常见的一种文件格式
  • 所有数据用一对大括号括起来
  • 大括号内部是键值对,键和值用冒号分隔
  • 多个键值对用逗号分隔
  • 字符串用双引号
  • 数字不需要引号
  • 列表用中括号
  • 对象用大括号
{
  "name": "tom",
  "age": 20,
  "addr": [1, 2, 3]
}

读取json文件的方法

  • 第一步要导入json模块
    • import json
  • 第二步打开json文件
    • json中有中文,一般字符集都是utf8,打开文件的时候要指定字符集为utf8
    • open(json文件名, “r”, encoding=“utf8”)
  • 第三步:调用json模块的load方法,读取文件内容
    • data = json.load(file)
  • 第四步:关闭open打开的文件
    • file.close()
import json
file = open("a.json", "r", encoding="utf8")
data = json.load(file) # 把json文件的内容转化为python的字典
file.close()
# print(data)
for n in data:
    print(n, data[n])

操作json文件常见错误

错误1:json格式错误

json.decoder.JSONDecodeError

错误2:扩展名不是json,是其他的

json文件的扩展名必须是.json

错误3:自己创建了一个文件名叫json.py

AttributeError: module 'json' has no attribute 'load'

写json文件

  • 导入json模块
    • import json
  • 用只写方式打开json文件
    • open(json文件,“w”, encoding=“utf8”)
  • 用dump方法把字典内容写入到json文件中
    • ensure_ascii = False代表中文不转义
  • 关闭文件
import json
dict1 = {"name":"刘备", "age":20, "sex":"男"}
file = open("data.json", "w", encoding="utf8")
json.dump(dict1, file, ensure_ascii=False)
file.close()

课堂练习-修改json文件内容

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 思路:
# 先把内容从test.json文件中读出来
# 读出来的结果是一个字典
# 把字典中键age对应 的值修改为30
# 再把字典写回到test.json文件中
import json
file = open("test.json", "r", encoding="utf8")
dict1 = json.load(file)
file.close()
dict1["age"] = 30
file = open("test.json", "w", encoding="utf8")
json.dump(dict1, file, ensure_ascii=False)
file.close()

在pycharm中安装课程需要的包-演示

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DAY--------------------------------------------10 (UnitTest)

UnitTest介绍

  • UnitTest是python自带的自动化测试框架
  • UnitTest主要包含的内容
    • TestCase(测试用例)
    • TestSuite(测试套件,把多个TestCase集成到一个测试TestSuite)
    • TestRunner(执行测试用例)
    • TestLoader(自动从代码中加载多个测试用例TestCase)
    • Fixture(UnitTest特性)

TestCase

  • 第一步:导入unittest模块
  • 第二步:实现一个类,这个类必须继承自unittest.TestCase类
  • 第三步:类中每个方法代表一个测试用例,方法名必须以test开头
import unittest

def my_sum(a, b):
    return a + b

class my_test(unittest.TestCase):
    def test_001(self):
        print(my_sum(5, 6))

    def test_002(self):
        print(my_sum(0, 3))


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 如果鼠标右键不出现unittest运行选项的处理方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

TestSuite

  • 把多个测试用例整合成一个测试套件
  • 使用方法
    • import导入unittest
    • import导入其他的包含测试用例的py文件
      • py文件的命名规则与变量名相同
    • 实例化unittest.TestSuite类的对象
    • 调用对象的addTest方法
      • addTest(py文件名.类名(“方法名”))
import unittest
import testcase_01

suite = unittest.TestSuite()
suite.addTest(testcase_01.my_test("test_001"))
suite.addTest(testcase_01.my_test("test_002"))
# 只是把测试用例添加到了测试套件中,并不是执行测试用例

  • 用unittest.makeSuite一次导入一个类中的所有测试方法
import unittest
import testcase_01

suite = unittest.TestSuite()
# suite.addTest(testcase_01.my_test("test_001"))
# suite.addTest(testcase_01.my_test("test_002"))
# 只是把测试用例添加到了测试套件中,并不是执行测试用例
suite.addTest(unittest.makeSuite(testcase_01.my_test))

TextTestRunner

  • 作用,执行在suite中的测试用例
  • 使用方法
    • 先实例化TextTestRunner的对象
    • 调用对象的run方法
      • 只要把suite做为参数,放入到run方法里面
import unittest
import testcase_01

suite = unittest.TestSuite()
# suite.addTest(testcase_01.my_test("test_001"))
# suite.addTest(testcase_01.my_test("test_002"))
# 只是把测试用例添加到了测试套件中,并不是执行测试用例
suite.addTest(unittest.makeSuite(testcase_01.my_test))

runner = unittest.TextTestRunner() # 实例化TextTestRunner的对象
runner.run(suite)  # 调用对象的run方法

TestLoader

  • 可以从指定目录查找指定py文件中的所有测试用例,自动加载到TestSuite中
import unittest
# 用TestLoader对象的discover方法来自动查找py,自动加载py文件中的方法
# 第一个参数是从哪里找py文件,"."从当前目录开始查找py文件
# 第二个参数是指定py文件的文件名,可以用通配符
suite = unittest.TestLoader().discover(".", "my*.py")
runner = unittest.TextTestRunner()
runner.run(suite)

TestSuite和TestLoader的使用区别

  • 当只是要执行py文件中多个测试用例中的几个,而不是全部执行那么适合用TestSuite的addTest加载指定的测试用例
  • 当要执行所有的py文件中的所有的测试用例,那么适合使用TestLoader

小结

  • 所有的TestCase最终都是用TextTestRunner来执行的
  • TextTestRunner执行的是TestSuite
  • 一个TestSuite中可以有多个TestCase

Fixture

  • 可以在测试用例执行执行之前自动调用指定的函数,在测试用例执行之后自动调用指定的函数
  • 控制级别
    • 方法级
      • 每个方法执行前和执行后都自动调用函数
    • 类级
      • 不管类中有多少方法,一个类执行前后都自动调用函数
    • 模块级
      • 不管一个模块(一个模块就是一个py文件)中有多少类,模块执行前后自动调用函数

方法级

  • 在TestCase,也就是测试用例所在的class中定义方法
  • def setUp(self) 当测试用例执行前,自动被调用
  • def tearDown(self) 当测试用例执行后,自动被调用
  • 如果一个TestCase中有多个测试用例,那么setUp和tearDown就会被自动调用多次

mytest.py内容修改如下:

import unittest

def my_sum(a, b):
    return a + b

class my_test(unittest.TestCase):
    def setUp(self):
        print("setup被自动调用了")
    def tearDown(self):
        print("teardown被自动调用了")

    def test_001(self):
        print(my_sum(5, 6))

    def test_002(self):
        print(my_sum(0, 3))

类级

  • 不管类中有多少方法,一个类开始的时候自动调用函数,结束的之后自动调用函数
  • 类级的fixture一定要是类方法
  • @classmethod def setUpClass(cls)类开始时自动调用的方法
  • @clasmethod def tearDownClass(cls)类结束的时候自动调用的方法

mytest.py修改如下:

import unittest

def my_sum(a, b):
    return a + b

class my_test(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setupclass自动调用了")
    @classmethod
    def tearDownClass(cls):
        print("teardownclass自动调用了")
    def setUp(self):
        print("setup被自动调用了")
    def tearDown(self):
        print("teardown被自动调用了")

    def test_001(self):
        print(my_sum(5, 6))

    def test_002(self):
        print(my_sum(0, 3))



模块级

  • 不管py文件中有多少个类,以及类中有多少方法,只自动执行一次
  • def setUpModule() 在py文件开始的时候自动调用
  • def tearDownModule() 在py文件结束的时候自动调用

修改后的mytest.py内容如下

import unittest

def setUpModule():
    print("setUpModule自动调用了")

def tearDownModule():
    print("tearDownModule自动调用了")

def my_sum(a, b):
    return a + b

class my_test1(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setupclass自动调用了")
    @classmethod
    def tearDownClass(cls):
        print("teardownclass自动调用了")
    def setUp(self):
        print("setup被自动调用了")
    def tearDown(self):
        print("teardown被自动调用了")

    def test_001(self):
        print(my_sum(5, 6))

    def test_002(self):
        print(my_sum(0, 3))

class my_test2(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setupclass自动调用了")
    @classmethod
    def tearDownClass(cls):
        print("teardownclass自动调用了")
    def setUp(self):
        print("setup被自动调用了")
    def tearDown(self):
        print("teardown被自动调用了")

    def test_001(self):
        print(my_sum(5, 6))

    def test_002(self):
        print(my_sum(0, 3))



fixture小结

  • 一定要在继承于unittest.TestCase这个类的子类中使用
  • setUP,tearDown, 每个方法执行开始和完毕后自动调用
  • setUPClass, tearDownClass, 每个类开始时候和结束时候自动调用
  • setUpModule, tearDownModule,每个py文件开始和结束的时候自动调用

断言

  • 让程序来判断测试用例执行结果是否符合预期

unittest断言

  • assertEqual(参数1, 参数2)
    • 如果参数1,参数2的值相等,断言成功,否则断言失败
    • 两个参数,有一个存放实际结果,有一个存放预期结果

修改后的mytest.py内容

import unittest

def setUpModule():
    print("setUpModule自动调用了")

def tearDownModule():
    print("tearDownModule自动调用了")

def my_sum(a, b):
    return a - b

class my_test1(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setupclass自动调用了")
    @classmethod
    def tearDownClass(cls):
        print("teardownclass自动调用了")
    def setUp(self):
        print("setup被自动调用了")
    def tearDown(self):
        print("teardown被自动调用了")

    def test_001(self):
        num1 = my_sum(5, 6)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, 11)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败

    def test_002(self):
        num1 = my_sum(0, 3)
        self.assertEqual(num1, 3)


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • assertIn(参数1, 参数2)
    • 如果参数1在参数2里面,断言通过,否则断言失败

修改后的mytest.py内容如下:

import unittest
import random

def setUpModule():
    print("setUpModule自动调用了")

def tearDownModule():
    print("tearDownModule自动调用了")

def my_sum(a, b):
    return a + b

def my_rand(): # 返回从1到5之间的一个随机数
    return random.randint(10, 50)

class my_test1(unittest.TestCase):
    def test_001(self):
        num1 = my_sum(5, 6)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, 11)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败

    def test_002(self):
        num1 = my_sum(0, 3)
        self.assertEqual(num1, 3)

    def test_003(self):
        num1 = my_rand()
        self.assertIn(num1, [1, 2, 3, 4, 5])


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参数化

测试用例中使用参数化的场景

  • 多个测试用例代码相同,只是测试数据不同,预期结果不同,可以把多个测试用例通过参数化技术合并为一个测试用例
import unittest
import random

def setUpModule():
    print("setUpModule自动调用了")

def tearDownModule():
    print("tearDownModule自动调用了")

def my_sum(a, b):
    return a + b

class my_test1(unittest.TestCase):
    def test_001(self):
        num1 = my_sum(5, 6)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, 11)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败

    def test_002(self):
        num1 = my_sum(0, 3)
        self.assertEqual(num1, 3)

    def test_003(self):
        num1 = my_sum(-3, 7)
        self.assertEqual(num1, 4)

    def test_004(self):
        num1 = my_sum(-4, -20)
        self.assertEqual(num1, -24)

    # 以上的测试用例,基本是一样的,测试用例的数据和预期结果不同



手工安装py包的过程

  • 把parameterized目录和parameterized-0.7.4.dist-info拷贝到python安装目录的Lib/site-packages下
  • 在pycharm中新建项目的时候,注意一个选项
    • 第一步:先新建了一个文件夹c:\file\mycode

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参数化

  • 第一步:导入from parameterized import parameterized
  • 第二步在方法上面用@parameterized.expand()修饰方法
    • expand()里面是一个列表
    • 列表里面放多个元组, 每个元组中的成员就代表调用方法使用的实参
    • 列表中有几个元组,方法就会自动被调用几次
import unittest
from parameterized import parameterized

def my_sum(a, b):
    return a + b

class my_test1(unittest.TestCase):
    # a是调用my_sum的第一个参数
    # b是调用my_sum的第二个参数
    # c是预期结果
    @parameterized.expand([(1, 2, 3), (5, 6, 110), (-1, 3, 2)])
    def test_001(self, a, b, c):
        num1 = my_sum(a, b)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, c)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

执行结果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参数化场景二

import unittest
from parameterized import parameterized

def my_sum(a, b):
    return a + b

list1 = [(1, 2, 3), (5, 6, 110), (-1, 3, 2)]

class my_test1(unittest.TestCase):
    # a是调用my_sum的第一个参数
    # b是调用my_sum的第二个参数
    # c是预期结果
    @parameterized.expand(list1)
    def test_001(self, a, b, c):
        num1 = my_sum(a, b)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, c)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败





参数化场景三:

import unittest
from parameterized import parameterized

def my_sum(a, b):
    return a + b

def get_data():  # 定义了一个函数,返回一个列表
    return [(1, 2, 3), (5, 6, 110), (-1, 3, 2)]

class my_test1(unittest.TestCase):
    # a是调用my_sum的第一个参数
    # b是调用my_sum的第二个参数
    # c是预期结果
    @parameterized.expand(get_data())
    def test_001(self, a, b, c):
        num1 = my_sum(a, b)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, c)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败


跳过(了解即可)

  • 可以通过@unittest.skip跳过指定的方法或者函数
  • 语法
@unittest.skip
def 方法名():
import unittest
from parameterized import parameterized

def my_sum(a, b):
    return a + b

def get_data():  # 定义了一个函数,返回一个列表
    return [(1, 2, 3), (5, 6, 11), (-1, 3, 2)]

class my_test1(unittest.TestCase):
    # a是调用my_sum的第一个参数
    # b是调用my_sum的第二个参数
    # c是预期结果
    @parameterized.expand(get_data())
    def test_001(self, a, b, c):
        num1 = my_sum(a, b)  # 定义变量num1得到my_sum函数的返回值
        self.assertEqual(num1, c)  # num1里存放的是实际结果,11是预期结果
        # 实际结果与预期结果相符,代表测试用例测试通过
        # 不相符代表测试用例测试失败
    @unittest.skip
    def test_002(self):
        print("test002")


通过TextTestRunner生成测试报告

  • 在实例化TextTestRunner对象的时候,需要写参数
stream=file, verbosity=2
file代表用open打开的一个文件
verbosity=2,固定
  • 第一步:用open,w方式打开测试报告文件
  • 第二步:实例化TextTestRunner对象
  • 第三步调用对象的run方法执行测试套件
  • 第四步:关闭open打开的文件
import unittest
# 用TestLoader对象的discover方法来自动查找py,自动加载py文件中的方法
# 第一个参数是从哪里找py文件,"."从当前目录开始查找py文件
# 第二个参数是指定py文件的文件名,可以用通配符
suite = unittest.TestLoader().discover(".", "my*.py")
# runner = unittest.TextTestRunner()
file = open("test01.txt", "w", encoding="utf8")
runner = unittest.TextTestRunner(stream=file, verbosity=2)
runner.run(suite)
file.close()

HTML测试报告

  • 把文件HTMLTestRunner.py拷贝到项目目录下
  • 在代码中导入模块from HTMLTestRunner import HTMLTestRunner
  • 调用HTMLTestRunner(stream=file, title=“我的第一个html测试报告”)
    • 第一个参数是用open打开的文件, 打开的文件扩展名一定是.html
    • open打开文件的时候,用wb,不用指定字符集
  • 调用runner对象的run方法执行测试套件
  • 关闭open打开的文件
import unittest
from HTMLTestRunner import HTMLTestRunner
# 用TestLoader对象的discover方法来自动查找py,自动加载py文件中的方法
# 第一个参数是从哪里找py文件,"."从当前目录开始查找py文件
# 第二个参数是指定py文件的文件名,可以用通配符
suite = unittest.TestLoader().discover(".", "my*.py")
# runner = unittest.TextTestRunner()
file = open("test01.html", "wb")  # 用wb代表用二进制写方式打开文件
# runner = unittest.TextTestRunner(stream=file, verbosity=2)
runner = HTMLTestRunner(stream=file, title="我的第一个html测试报告")
runner.run(suite)
file.close()

DAY--------------------------------------------11 (异常)

异常

  • 程序的错误有两种
  • 编码出错,不符合语言的语法
  • 运行时报错--------异常
  • 程序运行期间是要避免异常
  • 程序一旦出现异常就终止运行

捕获异常

  • 语法
try:
    可能出现异常的语句
except:
    出现异常后会自动执行的代码
    
如果try下面的代码没出现异常,那么except下面的代码不会执行
只有try下面的代码出现异常,except下面的代码才会执行
一旦异常被try捕捉,那么程序就不会报错终止了
try:
    a = int(input("请输入一个整数"))
except:
    print("输入不正确")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

捕捉不同类型异常

  • 语法
try:
    可能出异常的代码
except 异常类型1:
    出现异常类型执行的代码
except 异常类型2:
    出现异常类型执行的代码
except:
    出现未知异常执行的代码
try:
    a = int(input("请输入一个整数"))
    b = int(input("请输入一个整数"))
    print(a / b)
except ValueError:
    print("请输入一个可以转化整数")
except ZeroDivisionError:
    print("除数不能为0")
except:
    print("未知错误")

# ValueError: 输入的值不能转化为整数
# ZeroDivisionError: 除数为0的时候报的错误

  • 课堂练习-计算器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

try:
    num1 = int(input("请输入num1的值"))
    num2 = int(input("请输入num2的值"))
    op1 = input("请输入op1的值")
    if op1 == "+":
        print(num1 + num2)
    elif op1 == "-":
        print(num1 - num2)
    elif op1 == "*":
        print(num1 * num2)
    elif op1 == "/":
        print(num1 / num2)
    else:
        print("op1值不对")
except ValueError:
    print("请输入一个可以转化整数")
except ZeroDivisionError:
    print("除数不能为0")
except:
    print("未知错误")

没有异常发生执行的代码

  • 语法
try:
    可能出现异常的代码
except:
    发生异常要处理的代码
else:
    没有异常发生要执行的代码
try:
    a = int(input("请输入a的值"))
    b = int(input("请输入b的值"))
    print(a / b)
except:
    print("异常发生")
else:
    print("没有异常发生")
  • 捕捉未知异常显示系统异常提示信息
try:
    a = int(input("请输入a的值"))
    b = int(input("请输入b的值"))
    print(a / b)
except Exception as result: # 捕捉未知异常,把未知异常系统的错误提示显示出来
    print(result)
  • 无论是否异常都要执行的代码
try:
    可能出现异常的代码
except:
    出现异常要处理的代码
finally:
    无论是否异常都要执行的代码
try:
    a = int(input("请输入a的值"))
    b = int(input("请输入b的值"))
    print(a / b)
except:
    print("异常发生")
finally:
    print("不论是否有异常都要执行的代码")
  • 异常完整语法
try:
    可能出现异常的代码
except 指定异常类型1:
    异常执行代码
except 指定异常类型2:
    异常执行代码    
except Exception as result:
    异常执行代码
else:
    没有异常执行代码
finally:
    无论是否有异常执行代码
try:
    a = int(input("请输入a的值"))
    b = int(input("请输入b的值"))
    print(a / b)
except ValueError:
    print("请输入正确的整数")
except ZeroDivisionError:
    print("除数不能为0")
except Exception as result:
    print("未知异常", result)
else:
    print("代码没有异常发生")
finally:
    print("代码执行完成")

主动抛出异常

  • 可以通过代码人为的抛出异常
  • 语法
raise Exception("异常描述")
  • 主动抛出的异常同样会导致程序报错终止
print("开始")
raise Exception("主动抛出的异常")  # 这个异常是自己人为抛出
# 不论什么样的异常,只有不捕捉,代码就会报错终止
print("结束")  # 这里的print执行不了,因为上面一句代码已经抛出异常了,程序终止了

捕捉主动抛出的异常

  • 不管是什么异常,都需要代码捕捉,不然程序会报错
# 计算器,当用户输入的不是+-*/会抛出异常,并捕捉这个异常
try:
    num1 = int(input("请输入整数"))
    num2 = int(input("请输入整数"))
    op1 = input("请输入+-*/")
    if op1 != "+" and op1 != "-" and op1 != "*" and op1 != "/":
        raise Exception("请输入正确的+-*/")
    if op1 == "+":
        print(num1 + num2)
    elif op1 == "-":
        print(num1 - num2)
    elif op1 == "*":
        print(num1 * num2)
    else:
        print(num1 / num2)

except Exception as result:
    print(result)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 设计一个函数,如果参数str1中有数字返回true,否则返回false
def digital(str1):
    for n in str1:
        if n >= "0" and n <= "9":
            return True
    return False

try:
    name = input("请输入姓名")
    if digital(name): # 条件成立,抛出异常
        raise Exception("名字不允许有数字")
    age = int(input("请输入年龄"))
    if age < 0:
        raise Exception("年龄不能小于0")
except Exception as result:
    print(result)

当一个函数返回一个布尔值,做为条件放到if或者while后面的时候
if 函数名 == True  等价 if 函数名  如果函数返回True,等于条件成立
    如果返回返回False等于条件不成立

如果一个函数返回False,那么就执行if语句
if not 函数名 :

模块

  • 一个py文件就是一个模块
  • 一个项目是由多个py文件构成的,所以说一个项目是多个模块组成
  • 模块名,也就是py文件名要符合变量的命名规则
    • 一般习惯模块名用小写字母,如果有多个单词,单词之间用下划线分隔

import

  • 在一个py文件中使用另一个py文件中内容,需要先使用import导入模块
  • 语法
import 模块名
模块名.函数
# 在module2.py里面使用module1.py中定义的函数
import module1
print(module1.my_sum(3, 4))

module1.py

def my_sum(a, b):
    return a + b

  • 导入模块同时起一个别名
import 模块名 as 别名
别名.函数名
# 在module2.py里面使用module1.py中定义的函数
import module1 as m
print(m.my_sum(3, 4))

from import导入指定内容

  • 从指定模块中导入指定的内容
  • import默认会把模块中所有内容导入,from import会有选择的导入内容
  • 语法一
from 模块名 import 函数名
调用函数的时候,不需要前面在接模块名.,直接写函数名调用即可
  • 语法二
from 模块名 import *
导入所有内容,使用内容的时候,不需要写模块名.

module1.py

def my_sum(a, b):
    return a + b

def my_max(a, b):
    if a > b:
        return a
    else:
        return b

module3.py

# 只想导入module1中的my_max函数
from module1 import my_max
print(my_max(4, 5))

__name__属性

  • 每一个py文件都有一个属性__name__
  • 如果这个py文件是正在执行的模块,那么name属性的值为__main__
  • 如果这个py文件是被其他py文件import导入调用的,那么name属性的值就是这个py文件的模块名

module4.py


def my_test():
    print(__name__)

# my_test()  当前如果执行的就是module4这个模块,那么属性__name__的值为"__main__"

module5.py

import module4
module4.my_test()  # 调用module4中的my_test函数
# 这里的my_test会输出module4

  • 包就是一个特殊的目录
  • 一个目录下需要有__init__.py文件
  • 使用包的目的是一次性可以把一个目录下所有的模块通过一条import语句导入

创建步骤的演示

  • 第一步:在项目里建立一个目录my_pack
  • 第二步在my_pack目录里创建两个py文件,a1.py和a2.py,内容如下

a1.py

def my_max(a, b):
    if a > b:
        return a
    else:
        return b

a2.py

def my_sum(a, b):
    return a + b
  • 第三步,在my_pack目录下创建__init__.py文件

__init__.py

from . import a1
from . import a2
  • 第四步:在my_pack的上级目录建立一个module6.py文件,建立这个文件的目的是要使用my_pack包

module6.py

# module6要使用包my_back
import my_pack
print(my_pack.a1.my_max(3, 5))
print(my_pack.a2.my_sum(3, 5))

  • 使用包中的函数
import 包名
包名.模块名.函数名
  • 使用包注意的点
    • 不管目录下有多少模块
    • 只有在__init__.py文件中通过import导入模块才能使用
    • __init__.py里面的from 后面是个相对路径

导入包中指定函数

  • 语法
from.模块 import 函数
直接写函数名调用函数即可
from my_pack.a1 import my_max
from my_pack.a2 import my_sum
print(my_max(4, 6))
print(my_sum(4, 6))

课堂练习-my_pack1包

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_pack1/m1.py

def m1_func():
    print("我是m1的func函数")

def m1_test():
    print("我是m1的test函数")

my_pack1/m2.py

def m2_func():
    print("我是m2的func函数")

my_pack1/__init__.pu

from . import m1
from . import m2

module8.py

# import my_pack1
# my_pack1.m1.m1_func()
# my_pack1.m1.m1_test()
# my_pack1.m2.m2_func()
from my_pack1.m1 import m1_test
from my_pack1.m1 import m1_func
from my_pack1.m2 import m2_func
m1_test()
m1_func()
m2_func()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

今天这篇文章就到这里了,大厦之成,非一木之材也;大海之阔,非一流之归也。感谢大家观看本文

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录一下(goland导入其他包方法编译不了爆红但能正常使用)

在goLand里面新建go文件,里面放了一个方法,首字符也大写了,但是在别的包里面报错显示无法识别,爆红显示,但是项目能正常运行,这里说下我的解决方案 即可解决

软件设计师——操作系统

&#x1f4d4;个人主页&#x1f4da;&#xff1a;秋邱-CSDN博客☀️专属专栏✨&#xff1a;软考——软件设计师&#x1f3c5;往期回顾&#x1f3c6;&#xff1a;C: 类和对象&#xff08;上&#xff09;&#x1f31f;其他专栏&#x1f31f;&#xff1a;C语言_秋邱 一、操作系统…

粘接黑科技标杆专业展会-ASE CHINA 2024 震撼开幕!

2024年9月19日&#xff0c;第27届国际胶粘剂及密封剂展暨第19届国际胶粘带与薄膜展&#xff08;以下简称ASE CHINA 2024&#xff09;在上海新国际博览中心N3-N4-N5馆璀璨揭幕。ASE CHINA作为粘接新材料产业风向标&#xff0c;历经27年的辛苦耕耘&#xff0c;与业界同仁并肩而行…

发布策略说明

发布策略说明 发布策略 区别 标准发布 在部署新版本应用时删除旧版本应用。发布过程中&#xff0c;您的服务会出现短暂中断。 蓝绿发布 应用更新时生成蓝绿两个版本&#xff0c;两个版本互相热备&#xff0c;通过切换路由权重的方式实现不同版本应用的上下线。 该发布策略具…

Moshi: a speech-text foundation model for real time dialogue

视频号 挺神奇的东西 整下来 kyutai-labs/moshi (github.com) git clone https://github.com/kyutai-labs/moshi.git 在线体验 moshi.chat 结束后 点击Download audio Download video 可以下载音频与视频 &#xff08;不过是webm格式&#xff09; 发行版 已上传至资源 小…

Qt (19)【Qt 线程安全 | 互斥锁QMutex QMutexLocker | 条件变量 | 信号量】

阅读导航 引言一、互斥锁1. QMutex&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例基本需求⭕thread.h⭕thread.cpp⭕widget.h⭕widget.cpp 2. QMutexLocker&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;使用示例 3. QReadWriteLocker、QR…

AI论文写作PPT思维导图PC小程序开发

AI论文写作PPT思维导图PC小程序开发 AI智能PPT功能 一键生成PPT大纲、一键扩写大纲内容、单独扩写某个大纲内容、一键生成内容关键词、单项内容关键词生成、新增大纲项、修改大纲、删除大纲、选择PPT模板、单页模板一键切换、在线编辑模板&#xff1b;支持导出PPTX、JPEG、&am…

nodejs 013:Prect 样式复用(multiple classes)例子

Prect 简单示例 Prect 为使用相同的现代 API 的快速 3kB React 替代方案。代码形式与 React 基本相同。部分语法区别可见 prect-differences-to-react。以下是一个 Prect 简单示例。 Button目录Button.css&#xff1a; .this {display: inline-block;padding: 3px 8px;margi…

执行网络攻击模拟的 7 个步骤

在进攻和防守策略方面&#xff0c;我们可以从足球队和美式足球队身上学到很多东西。球员们会分析对方球队的策略&#xff0c;找出弱点&#xff0c;相应地调整进攻策略&#xff0c;最重要的是&#xff0c;练习、练习、再练习。作为最低要求&#xff0c;网络安全部门也应该这样做…

基于微信的设备故障报修管理系统设计与实现+ssm论文源码调试讲解

2相关技术 2.1微信小程序 小程序是一种新的开放能力&#xff0c;开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。尤其拥抱微信生态圈&#xff0c;让微信小程序更加的如虎添翼&#xff0c;发展迅猛。 2.2 MYSQL数据…

一文彻底搞懂大模型 - OpenAI o1(最强推理模型)

最近这一两周看到不少互联网公司都已经开始秋招提前批面试了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些…

举例说明:自然语言处理实战项目

自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能领域的一个重要分支&#xff0c;旨在使计算机能够理解、解释和生成人类语言。以下是一些NLP实战项目的示例&#xff1a; 1. 情感分析&#xff08;Sentiment Analysis&#xff09; 项目描述: …

用 HTML + JavaScript DIY 一个渐进式延迟法定退休年龄测算器

为减轻社会和个人因退休年龄变化带来的冲击&#xff0c;近日&#xff0c;全国人民代表大会常务委员会正式发布了关于实施渐进式延迟法定退休年龄的重要决定。 根据该决定&#xff0c;我国将同步启动对男、女职工法定退休年龄的延迟计划。这一调整将采取渐进式的方式进行&#…

09年408考研真题-数据结构

数据结构 10.【2009统考真题】为解决计算机主机与打印机之间速度不匹配的问题&#xff0c;通常设置一个打印数据缓冲区&#xff0c;主机将要输出的数据依次写入该缓冲区&#xff0c;而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是(B&#xff09;。 A.栈 …

unix中如何查询和修改进程的资源限制

一、前言 一个进程在运行时&#xff0c;会用到各种资源&#xff0c;比如cpu的使用时间、内存空间、文件等等。那么&#xff0c;一个进程能够占用多少资源呢&#xff1f;cpu使用的时间有多长&#xff1f;进程空间有多大&#xff1f;能够创建多少个文件&#xff1f;这个就是本文…

数字IC设计\FPGA 职位经典笔试面试整理--基础篇1

注&#xff1a; 资料都是基于网上一些博客分享和自己学习整理而成的 1&#xff1a;什么是同步逻辑和异步逻辑&#xff1f; 同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。 同步时序 逻辑电路的特点&#xff1a;各触发器的时钟端全部连接在一…

蚁群算法(ACO算法)求解实例---旅行商问题 (TSP)

目录 一、采用ACO求解 TSP二、 旅行商问题2.1 实际例子&#xff1a;求解 6 个城市的 TSP2.2 **求解该问题的代码&#xff0c;代码&#xff08;完整代码关注底部微信公众号获取&#xff09;**2.3 代码运行过程截屏2.4 代码运行结果截屏&#xff08;后续和其他算法进行对比&#…

Acwing数据结构:单链表

单链表 主要思想&#xff1a;使用数组实现链表(而不用结构体&#xff0c;结构体代码更长&#xff0c;后续图论也是基于数组实现&#xff09;&#xff0c;即静态链表。因为动态链表使用new申请空间需要较多的时间&#xff0c;而算法要求的是以较少的时间完成任务。 单链表&…

软件测试八股文

Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自…

appimage 软件创建桌面快捷图标

1、appimage 软件创建桌面快捷图标 1&#xff09;下载 AppImage 文件 首先&#xff0c;确保你已经下载了 AppImage 文件&#xff0c;并且该文件具有可执行权限。你可以通过以下命令为 AppImage 文件添加可执行权限&#xff1a; chmod x /path/to/your-app.AppImage2&#xff…