Python语言基础教程(下)4.0

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

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

✨博客主页: 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.mfbz.cn/a/881490.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

十六 未来信息综合技术(考点篇)

1 信息物理系统技术 信息物理系统(CPS)是控制系统、嵌入式系统的扩展与延伸&#xff0c;其涉及的相关底层理论技术源于对嵌入式技术的应用与提升。 CPS 通过集成先进的感知、计算、通信、控制等信息技术和自动控制技术&#xff0c;构建了物理空间与信息空间中人、机、物、环境…

OpenCV特征检测(3)计算图像中每个像素处的特征值和特征向量函数cornerEigenValsAndVecs()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算图像块的特征值和特征向量用于角点检测。 对于每一个像素 p &#xff0c;函数 cornerEigenValsAndVecs 考虑一个 blockSize blockSize 的邻…

mysql为什么建议创建字段的时候not null

相信大家在建表或者给表新加字段的时候&#xff0c;一些老司机们都会建议我们&#xff0c;字段要定义为not null&#xff0c;原因呢是一是占用存储空间&#xff0c;另一个是避免出现一些意料之外的错误。当然针对这个问题&#xff0c;大家可能也会在网上去搜下&#xff0c;不过…

制作炫酷个人网页:用 HTML 和 CSS3 展现你的风格

你是否觉得自己的网站应该看起来更炫酷&#xff1f;今天我将教你如何使用 HTML 和 CSS3 制作一个拥有炫酷动画和现代设计风格的个人网页&#xff0c;让它在任何设备上看起来都无敌酷炫&#xff01; 哈哈哈哈哈哈哈哈,我感觉自己有点中二哈哈哈哈~ 目录 炫酷设计理念构建 HTML …

【电力系统】基于遗传算法的33节点电力系统无功优化及MATLAB实现

摘要 本文研究了基于遗传算法的33节点配电系统的无功优化问题。通过调整电容器的安装位置和容量&#xff0c;以最小化系统的无功损耗和电压偏差。研究使用遗传算法对无功优化问题进行求解&#xff0c;并在MATLAB环境中进行仿真实现。实验结果表明&#xff0c;该方法能够有效地…

零工市场小程序:推动零工市场建设

人力资源和社会保障部在2024年4月发布了标题为《地方推进零工市场建设经验做法》的文章。 零工市场小程序的功能 信息登记与发布 精准匹配、推送 在线沟通 权益保障 零工市场小程序作为一个找零工的渠道&#xff0c;在往后随着技术的发展和政策的支持下&#xff0c;功能必然…

★ C++进阶篇 ★ 二叉搜索树

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C进阶篇第三章----二叉搜索树 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 C基础篇专栏&#xff1a;★ C基础篇 ★_椎名澄嵐的博客-CSD…

【matlab】生成 GIF 的函数(已封装可直接调用)

文章目录 前言一、函数输入与输出二、函数代码三、例程&#xff08;可直接运行&#xff09;参考文献 前言 生成 gif 图片时遇到的问题&#xff0c;为了后续调用方便&#xff0c;封装为函数 一、函数输入与输出 输入&#xff1a; cell_figure: cell 数组&#xff0c;数组元素是…

git 更换远程地址的方法

需要将正在开发的代码远程地址改成新的地址&#xff0c;通过查询发现有三个方法可以实现&#xff0c;特此记录。具体方法如下&#xff1a; &#xff08;1&#xff09;通过命令直接修改远程仓库地址 git remote 查看所有远程仓库git remote xxx 查看指定远程仓库地址git remote…

ProtoBuf序列化框架介绍

文章目录 ProtoBuf介绍使用流程 QUICK START创建.proto文件注释语法编译部分代码展示使用接口运行结果 ProtoBuf介绍 ProtoBuf全称是Protocol Buffer&#xff0c;是一个数据结构的序列化和反序列化框架 他又很多好处&#xff0c;首先是他支持跨平台&#xff0c;支持Java、C、…

Mac 上,终端如何开启 proxy

文章目录 为什么要这么做前提步骤查看 port查看代理的port配置 bash测试 为什么要这么做 mac 上的终端比较孤僻吧&#xff0c;虽然开了&#xff0c;但是终端并不走&#x1fa9c;…产生的现象就是&#xff0c;浏览器可以访问&#x1f30d;&#xff0c;但是终端不可以访问&#…

创建Application(Qt)模板项目时的 Base class选择

在Qt中&#xff0c;当你使用Qt Creator新建一个Qt Widgets Application项目时&#xff0c;选择Base class是一个重要的步骤&#xff0c;因为它决定了你的主窗口或对话框将继承自哪个类&#xff0c;从而决定了你的应用程序将具有哪些基本的功能和外观。以下是一些常见的Base cla…

docker进入容器运行命令

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

3D生成技术再创新高:VAST发布Tripo 2.0,提升AI 3D生成新高度

随着《黑神话悟空》的爆火&#xff0c;3D游戏背后的AI 3D生成技术也逐渐受到更多的关注。虽然3D大模型的热度相较于语言模型和视频生成技术稍逊一筹&#xff0c;但全球的3D大模型玩家们却从未放慢脚步。无论是a16z支持的Yellow&#xff0c;还是李飞飞创立的World Labs&#xff…

双击就可以打开vue项目,而不用npm run dev

右键点击桌面或其他位置&#xff0c;选择“新建” -> “快捷方式”&#xff0c;在“对象的位置”处直接输入“npm run dev”&#xff0c;然后下一步 自定义一个快捷方式名称 完成后&#xff0c;桌面会创建一个快捷方式&#xff0c;右键快捷方式选择属性&#xff0c;可以看…

为什么 ECB 模式不安全

我们先来简单了解下 ECB 模式是如何工作的 ECB 模式不涉及链接模式&#xff0c;所以也就用不着初始化向量&#xff0c;那么相同的明文分组就会被加密成相同的密文分组&#xff0c;而且每个分组运算都是独立的&#xff0c;这也就意味着可以并行提高运算效率&#xff0c;但也正是…

prometheus通过nginx-vts-exporter监控nginx

Prometheus监控nginx有两种方式。 一种是通过nginx-exporter监控&#xff0c;需要开启nginx_stub_status,主要是nginx自身的status信息&#xff0c;metrics数据相对较少&#xff1b; 另一种是使用nginx-vts-exporter监控&#xff0c;但是需要在编译nginx的时候添加nginx-module…

Shader 中的光源

1、Shader 开发中常用的光源属性 Unity当中一共支持四种光源类型&#xff1a; 平行光&#xff08;Directional&#xff09;点光源&#xff08;Point&#xff09;聚光灯&#xff08;Spot&#xff09;面光源&#xff08;Area&#xff09;— 面光源仅在烘焙时有用 不管光源类型到…

Docker 华为云镜像加速器配置

​​ 操作说明 1. 安装/升级容器引擎客户端 推荐安装1.11.2以上版本的容器引擎客户端 2. 加速器地址 访问华为云容器镜像服务&#xff1a;https://console.huaweicloud.com/swr/ 获取加速器地址 https://xxxxxxxxx.mirror.swr.myhuaweicloud.com3. 配置镜像加速器 针对…

【Qt | QLineEdit】Qt 中使 QLineEdit 响应 鼠标单击、双击事件 的两个方法

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-09-14 …