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()
今天这篇文章就到这里了,大厦之成,非一木之材也;大海之阔,非一流之归也。感谢大家观看本文