python笔记

python学习笔记

1.python基础


python + selenium -> web自动化

python + appium -> 移动端自动化

python + requests -> 接口

语言分类:

编译型语言:C ->代码转换为二进制,效率高

解释型语言:python ->执行代码时,转化为二进制


1.1注释

  • 单行注释:#

    # 注释AAA
    快捷键 Ctrl(cmd) /
    
  • 多行注释:“”“/’‘’

    """
    print("AAA")
    """
    '''
    print('AAA')
    '''
    
  • cmd中运行python代码:

    • python + 代码文件名

1.2变量

  • 变量:

    • 作用:是⽤来存储数据的(在程序代码中出现的数据,想要保存下
      来使⽤, 就必须使⽤变量), 如: 测试数据, ⽤户名, 密码, 验
      证码
    • 注意:变量必须先定义(保存数据)后使⽤(取出数据)
  • 定义变量:

    • 变量名 = 数据值
    • name = ‘张三’ # 定义变量name,存储的数据是张三
  • 命名规范:

      1. 必须由字⺟ 数字和下划线组成, 并且不能以数字开头

      2. 不能使⽤ Python 中的关键字作为变量名

      3. 区分⼤⼩写

      4. 建议性的命名

        1. 驼峰命名法

          ⼤驼峰: 每个单词的⾸字⺟⼤写 MyName

          ⼩驼峰: 第⼀个单词的⾸字⺟⼩写,其余单词的⾸字⺟⼤写 myName

        2. 下划线连接法: 每个单词之间使⽤下划线连接 my_name

          Python 中变量的定义使用的是下划线连接

        3. ⻅名知意:

          name:名字 age:年龄

1.3数据类型

  • 数字类型
    • 整型 (int ) , 就是整数 , 即不带⼩数点的数
    • 浮点型( float ), 就是⼩数
    • 布尔类型(bool), 只有两个值
      • 真 True , 1
      • 假 False 0, ⾮ 0 即真
  • 非数字类型
    • 字符串: (str) 使⽤引号引起来的就是字符串
    • 列表 (list) [1, 2, 3, 4]
    • 元组(tuple) (1, 2, 4, 4)
    • 字典 (dict) {‘name’: ‘⼩明’, ‘age’: 18}
  • type() 函数: type(变量) 获取变量的数据类型
  • 类型转换:变量 = 要转换为的类型(原数据)
    • int() 将其他类型转换为 int 类型
      • 可以将 float类型的数字转换为 整型
      • 可以将 整数类型的字符串 转换为 整型 3 123
    • float() 将其他类型转换为 浮点型
      • 可以将 int 类型转换为 浮点型 float(3) —> 3.0
      • 可以将 数字类型的字符串(整数类型和⼩数类型) 转换为浮点型
    • str() 将其他类型转换为 字符串类型
      • 任何类型都可以使⽤ str() 将其转换为字符串, ⼀般都是直接加上引号

1.4输入输出

  • 输入:获取用户使用键盘录入的内容

    • input()
    • 变量 = input(‘提示信息:’)
      • 变量的数据类型一定是str
  • 输出:将数据结果打印到控制台

    • print()
  • 格式化输出

    • % 格式化输出占位符号

      • %d 占位, 填充 整型数据 digit
        • %0nd 指定占位
      • %f 占位. 填充 浮点型数据 float
        • %.nf 保留小数尾数
      • %s 占位, 填充 字符串数据 string
      name = '⼩明' # 可以使⽤ input 输⼊
      age = 18 # 可以使⽤ input 输⼊
      height = 1.71 # 可以使⽤ input 输⼊
      
      print('我的名字是 %s, 年龄是 %d, 身⾼是 %f m' %(name, age, height))
      
    • F-string( f字符串的格式化⽅法) python>=3.6

      • 需要在字符串的前边加上 f"" 或者 F""
      • 占位符号统⼀变为 {}
      • 需要填充的变量 写在 {} 中
      name = '⼩明' # 可以使⽤ input 输⼊
      age = 18 # 可以使⽤ input 输⼊
      height = 1.71 # 可以使⽤ input 输⼊
      
      print(f'我的名字是 {name}, 年龄是 {age}, 身⾼是{height} m')
      
    • 字符串.format()

      • 任意版本
      • 需要用变量的地方使用 {} 占位
      • ‘{}, {}, …’.format(变量, 变量, …)
      print('我的名字是 {}, 年龄是 {}, 身高是 {} m'.format(name,age, height))
      

1.5运算符

image-20240212003648536

  • 比较运算符

    • ⽐较运算符得到都是 bool 类型

      > < >= <=

      == 判断两个数是否相等, 相等为 True, 不相等为 False

      != 判断两个数是否不相等, 不相等为 True, 相等为 False

  • 逻辑运算符:

    • and 逻辑与 和,并且 and 连接两个条件,都必须为 True, 整体结果才为 True, 即一假为假 (当第一个条件为False 的时候,第二个条件就不再判断)
    • or 逻辑或 或者 or 连接的两个条件, 只要有一个条件为 True , 整体结果就为 True, 即 一真为真 (当第一个条件为 True的时候,第二个条件就不再判断)
    • not 逻辑非 取反 not 后边的条件, 如果本来是 True,变为 False, 本来是 False,变为 True
  • 赋值运算符:

    • 赋值运算符 =, 作用就是将等号右边的值保存到等号左边的变量中

      复合赋值运算符(将算术运算符和赋值运算符进行结合)

      += -= *= /= //= %=

      a += b ===> a = a + b

1.6判断

  • 基本语法:

    if 判断条件:
        书写条件成立(),执行的代码
        书写条件成立(),执行的代码
        
    顶格书写,没有缩进的代码,if无关, 不管条件是否成立,都会执行
    
  • if else结构:

    if 判断条件1:
        书写条件1成立(),执行的代码
    elif 判断条件2:
        条件2成立,代码
    else:
        书写条件12不成立(), 执行的代码
    
  • if嵌套:

    if 判断条件1:
        判断条件1成立,执行的代码
    	if 判断条件2:
        	判断条件2成立,执行的代码
    	else:
        	判断条件2不成立,执行的代码
    else:
    	判断条件1不成立,执行的代码
    

1.7循环

  • while循环:

    1. 设置循环的初始条件(计数器)
    2. 书写循环的判断条件
    while 判断条件:
    	# 3. 需要重复执行的代码
    	# 4. 改变循环的初始条件(计数器)
        
    # 1. while 是关键字
    
    • break: 终⽌循环, 即代码执⾏遇到 break, 循环不再执⾏,⽴即结束
    • continue: 跳过本次循环. 即代码执⾏遇到 continue,本次循环剩下的代码不再执⾏, 继续下⼀次循环
  • for循环:

    for循环也可以让指定的代码重复执⾏ (循环)
    for循环可以遍历容器中的数据(
        遍历: 从容器中把数据⼀个⼀个取出
        容器: 可以简单理解为盒⼦, 盒⼦中可以存放很多的数据
    (字符串 str, 列表 list, 元组 tuple, 字典 dict)
    )
    for 循环 也可以称为 for 遍历
    -------------
    for 变量名 in 容器:
        重复执⾏的代码
    ---------
    for 变量 in range(n):
        重复执⾏的代码
    
    • range() 是 Python 中的函数, 作⽤使⽤可以⽣成[0, n) 之间的整数, 不包含 n 的,有 n 个数字, 所以这个循环循环 n 次
    • 想让 for 循环循环多少次,n 就写⼏
    • 变量的值 也是每次循环从 [0, n) 取出⼀个值, 第⼀次取得是 0 ,最后⼀次取得是 n-1
    • range(a, b) 作⽤是⽣成 [a, b) 之间的整数数字, 不包含 b

1.8字符串

1.8.1字符串
  • 字符串:
    • 使⽤引号(单引号, 双引号, 三引号)引起来的内容就是字符串
      • 字符串本身包含单引号, 则在定义的时候不能使⽤单引号
        • 转义字符 \
      • 字符串本身包含双引号, 则在定义的时候不能使⽤双引号
  • 下标:
    • 就是指字符在字符串中的位置编号, 这个编号就是下标
    • 正向从左到右,从0开始(Python 中⽀持负数下标,从右到左进⾏编号的, 从-1 开始)
1.8.2切片
  • 概念:可以获取字符串中多个字符(多个字符的下标是有规律的,等差数列)

  • 语法:字符串[start : end : step]

    • start 是开始位置的下标, end 是结束位置的下标(注意,不能取到这个位置的字符) step 步⻓,等差数列的差值, 所取的相邻字符下标之间的差值,默认是 1, 可以不写

    • 例:

      • [1:5:1] # 1 2 3 4
      • [1:5:2] # 1 3
      str1 = 'abcdefg'
      # 1. 获取 abc 字符
      print(str1[0:3:1]) # abc
      # 1.1 如果步⻓是 1 可以不写, 最后⼀个冒号也不写
      print(str1[0:3]) # abc
      # 1.2 如果开始位置为 0 ,可以不写, 但是冒号必须有
      print(str1[:3]) # abc
      # 2. 获取 efg 字符
      print(str1[4:7]) # efg
      print(str1[-3:7]) # efg
      # 2.1 如果最后⼀个字符也要取, 可以不写, 但是冒号必须有
      print(str1[4:]) # efg
      # 2.2 如果开始和结束都不写, 获取全部内容, 但是冒号必须有
      print(str1[:]) # abcdefg
      # 3. 获取 aceg # 0 2 4 6, 所以步⻓为 2
      print(str1[0:7:2]) # aceg
      print(str1[::2]) # aceg
      # 4. 特殊应⽤, 步⻓为负数, 开始和结束不写,意思全变, ⼀般
      不⽤管,只有⼀种使⽤场景
      # 反转(逆置) 字符串 字符串[::-1]
      print(str1[::-1]) # gfedcba
      
1.8.3方法
  • find()方法
    • 字符串.find(sub_str, start, end)
    • 作⽤: 在字符串中查找是否存在 sub_str 这样的字符串
      • sub_str: 要查找的⼩的字符串
      • start: 开始位置, 从哪个下标位置开始查找, ⼀般不写,默认是 0
      • end: 结束位置, 查找到哪个下标结束, ⼀般不写,默认是len()
      • 返回(代码执⾏之后会得到什么, 如果有返回,就可以使⽤变量保存):
        • 如果在字符串中找到了 sub_str , 返回 sub_str第⼀次出现的正数下标(sub_str 中第⼀个字符在⼤字符串中的下标)
        • 如果没有找到,返回 -1
  • replace()方法
    • 字符串.replace(old_str, new_str, count) # 将字符串中old_str 替换为 new_str
      • old_str: 被替换的内容
      • new_str: 替换为的内容
      • count: 替换的次数, ⼀般不写,默认是全部替换
      • 返回: 替换之后的完整的字符串, 注意: 原来的字符串没有发⽣改变
  • split()拆分方法
    • 字符串.split(sep, maxsplit) # 将字符串按照 sep 进⾏分割(拆分)
      • sep, 字符串按照什么进⾏拆分, 默认是空⽩字符(空格, 换⾏\n, tab键\t)
      • max_split, 分割次数,⼀般不写, 全部分割
      • 返回: 将⼀个字符串拆分为多个,存到列表中
      • 注意: 如果 sep 不写, 想要指定分割次数 则需要按照如下⽅式使⽤
        • 字符串.split(maxsplit=n) # n 是次数
  • join()链接方法
    • 字符串.join(列表) # 括号中的内容主要是列表,可以是其他容器
    • 作⽤: 将字符串插⼊到列表中每相邻的两个数据之间, 组成⼀个新的字符串
      • 列表中的数据使⽤使⽤ 逗号隔开的
      • 注意点: 列表中的数据必须都是字符串, 否则会报错

2.容器和函数

2.1 列表

  • 定义:

    • 变量 = [数据, 数据, …]
    • 列表 list, 是使⽤最多的⼀种容器(数据类型)
    • 列表中可以存储多个数据, 每个数据之间使⽤逗号隔开
    • 列表中可以存放任意类型的数据
  • 列表支持下标和切片长度

    list1 = ['⼩明', 18, 1.71, True]
    # 获取第⼀个数据,名字
    print(list1[0])
    # 获取最后⼀个数据
    print(list1[-1])
    # 第⼀第⼆个数据
    print(list1[0:2]) # ['⼩明', 18]
    # 列表⻚⽀持 len() 求⻓度的, 求数据元素个数
    print(len(list1)) # 4
    
  • 查找

    • 查找列表数据下标
      • 列表.index(数据, start, end) 使⽤和 find ⽅法⼀样,同时在字符串中也有 index ⽅法
      • 区别: 返回, index() ⽅法,找到返回第⼀次出现的下标, 没有找到代码直接报错
    • 判断存在
      • 判断容器中某个数据是否存在可以使⽤ in 关键字
      • 数据 in 容器 # 如果存在返回 True ,如果不存在,返回 False
    • 统计出现次数
      • 统计出现的次数,使⽤的是 count() ⽅法
      • 列表.count(数据) # 返回 数据出现的次数
    my_list = [1, 3, 5, 7, 2, 3]
    # 找 数据 3 出现的下标
    num = my_list.index(3)
    print(num) # 1
    # 找 数据 4 出现的下标
    # num1 = my_list.index(4) # 代码会报错
    if 4 in my_list:
        num1 = my_list.index(4)
        print(num1)
    else:
        print('不存在数据 4')
    # my_list.count(4) 统计 数据 4 出现的次数
    if my_list.count(4) > 0:
        num1 = my_list.index(4)
     	print(num1)
    else:
     	print('不存在数据 4')
    
  • 添加数据

    • 尾部添加
      • 列表.append(数据) # 将数据添加到列表的尾部
      • 返回: 返回的 None(关键字,空), ⼀般就不再使⽤ 变量 来保存返回的内容
      • 想要查看添加后的列表,需要打印的是列表
    • 指定下标添加
      • 列表.insert(下标, 数据) # 在指定的下标位置添加数据,如果指定的下标位置本来有数据, 原数据会后移
      • 返回: 返回的 None(关键字,空), ⼀般就不再使⽤ 变量 来保存返回的内容
      • 想要查看添加后的列表,需要打印的是列表
    • 列表合并
      • 列表1.extend(列表2) # 将列表 2 中的所有数据逐个添加的列表1 的尾部
      • 返回: 返回的 None(关键字,空), ⼀般就不再使⽤ 变量 来保存返回的内容
      • 想要查看添加后的列表,需要打印的是列表
    my_list = []
    print(my_list) # []
    # 1. 想列表中添加数据 郭德纲
    my_list.append('郭德纲')
    print(my_list) # ['郭德纲']
    # 2. 向列表的尾部添加 郭麒麟
    my_list.append('郭麒麟')
    print(my_list) # ['郭德纲', '郭麒麟']
    # 3. 在下标位置为 1 的位置添加数据 '岳岳
    my_list.insert(1, '岳岳')
    print(my_list) # ['郭德纲', '岳岳', '郭麒麟']
    # 4. 在下标位置为 1 的位置添加数据 于谦
    my_list.insert(1, '于谦')
    print(my_list) # ['郭德纲', '于谦', '岳岳', '郭麒麟']
    # 5. 定义新的列表 list1
    list1 = ['孙越', '烧饼']
    # 将 list1 中数据逐个添加到 my_list 中
    my_list.extend(list1)
    print(my_list) # ['郭德纲', '于谦', '岳岳', '郭麒麟','孙越', '烧饼']
    # 将 list1 作为⼀个整体添加到 my_list
    my_list.append(list1)
    print(my_list) # ['郭德纲', '于谦', '岳岳', '郭麒麟','孙越', '烧饼', ['孙越', '烧饼']]
    
  • 修改:

    • 想要修改列中的指定下标位置的数据, 使⽤的语法是:
      • 列表[下标] = 数据 # 字符串中字符不能使⽤下标修改
  • 删除:

    • 在列表中删除中间的数据, 那么后⾯的数据会向前移动
    • 根据下标删除
      • 列表.pop(下标) # 删除指定下标位置对应的数据
      • 下标不写,默认删除最后⼀个数据(常⽤
      • 书写存在的下标, 删除对应下标位置的数据
      • 返回: 返回的删除的数据
    • 根据数值删除
      • 列表.remove(数据值) # 根据数据值删除
      • 返回: None
      • 注意: 如果要删除的数据不存在, 会报错
    • 清空
      • 列表.clear()
  • 反转(倒置)

    • 字符串中 反转倒置: 字符串[::-1]
    • 列表中 反转和倒置:
      • 列表[::-1] # 使⽤切⽚的⽅法,会得到⼀个新列表, 原列表不会发⽣改变
      • 列表.reverse() # 直接修改原列表, 返回 None
  • 复制:

    • 使⽤切⽚
      • 变量 = 列表[:]
    • 使⽤ copy ⽅法
      • 变量 = 列表.copy()
  • 排序:

    • 列表.sort() # 按照升序排序, 从⼩到⼤
    • 列表.sort(reverse=True) # 降序排序, 从⼤到⼩
    • 字符⽐⼤⼩,是⽐较字符对应的 ASCII 码值
      • A < Z < a < z
      • ord(字符) # 获取字符对应的 ASCII 的值
      • chr(ASCII 值) # 获取对应的 字符
      • 字符串⽐⼤⼩:对应下标位置字符的⼤⼩, 直到⽐出⼤⼩, 如果全部⽐完了,还没有⽐出⼤⼩,就是相等
  • 嵌套:

    • 列表嵌套, 列表中的内容还是列表
    person_info = [["张三", "18", "功能测试"], ["李四","20", "⾃动化测试"]]
    print(len(person_info)) # 2
    print(person_info[0]) # ['张三', '18', '功能测试']
    print(person_info[0][0]) # '张三'
    print(person_info[0][0][0]) # 张
    

2.2 元组

  • 定义:

    • 元组: tuple, 元组的特点和列表⾮常相似
      • 元组中可以存放任意类型的数据
      • 元组中可以存放任意多个数据
    • 区别:
      • 元组中的数据内容不能改变, 列表中的可以改变的
      • 元组使⽤ (), 列表 使⽤ []
    • 应⽤: 在函数的传参或者返回值中使⽤, 保证数据不会被修改
    • 定义方式:
      • 类实例化 : my_tuple = tuple()
      • 直接() : my_tuple = ()
  • 方法:

      1. 在元组中也可以使⽤ 下标和切⽚获取数据

      2. 在元组中存在 index ⽅法, 查找下标, 如果不存在,会报错

      3. 在元组中存在 count ⽅法, 统计数据出现的次数

      4. 在元组中可以使⽤ in 操作, 判断数据是否存在

      5. len() 统计个数

    • 以上⽅法的使⽤ 和列表中⼀样的

    # 1, 类实例化的⽅式
    # 1.1 定义空元祖(不会使⽤的)
    my_tuple1 = tuple()
    print(type(my_tuple1), my_tuple1) # <class 'tuple'>()
    # 1.2 类型转换
    # 可以将列表转换为元组, 只需要将 [], 变为 (), 同时 可以将元组转换列表 , 将() 变为 []
    my_tuple2 = tuple([1, 2, 3])
    print(my_tuple2) # (1, 2, 3)
    # 转换字符串, 和列表中⼀样,只是将列表的[] 变为()
    my_tuple3 = tuple('hello')
    print(my_tuple3) # ('h', 'e', 'l', 'l', 'o')
    # 2. 直接使⽤ () 定义
    my_tuple4 = (1, "⼩王", 3.14, False)
    print(my_tuple4)
    # 3. 特殊点, 定义只有⼀个数据的元组时, 数据后边必须有⼀个逗号
    my_tuple5 = (1,)
    print(my_tuple5) # (1,)
    print(my_tuple4[1]) # ⼩王
    

2.3 字典

  • 定义:

      1. 字典 dict, 字典中的数据是由键(key)值(value)对组成的

        (键表示数据的名字, 值就是具体的数据)

      2. 在字典中⼀组键值对是⼀个数据, 多个键值对之间使⽤ 逗号隔开

        变量 = {key: value, key:value, …}

      3. ⼀个字典中的键是唯⼀的,不能重复的, 值可以是任意数据

      4. 字典中的键 ⼀般都是 字符串,可以是数字, 不能是列表

    • 定义方式:

        1. 类实例化
        2. {}定义
    # 1. 使⽤ 类实例化的⽅法
    my_dict = dict()
    print(type(my_dict), my_dict) # <class 'dict'> {}
    # dict() 不能转列表和元组,字符串
    # 2. 直接使⽤{} 定义
    # 2.1 空字典
    my_dict1 = {}
    print(type(my_dict1), my_dict1) # <class 'dict'> {}
    # 2.2 ⾮空字典, ⼩明('name') 18('age') 1.71('height')True(is_men) 抽烟 喝酒 烫头('like')
    my_dict2 = {"name": "⼩明", "age": 18, "height":1.71, "is_men": True, "like": ["抽烟", "喝酒", "烫头"]}
    print(my_dict2)
    print(len(my_dict2)) # 5
    
  • 增加,修改字典

    • 语法:
      • 字典[键] = 数据值
      • 如果键已经存在,就是修改数据值
      • 如果键不存在,就是添加数据(即添加键值对)
  • 删除:

    • 删除指定键值对
      • del 字典[键]
      • 字典.pop(键) # 键必须书写
    • 清空
      • 字典.clear()
  • 查询:

    • 使用 字典[键]
      • 字典[键]
        • 如果键存在 返回键对应的数据值
        • 如果键不存在, 会报错
    • 使用 字典.get(键)
      • 字典.get(键, 数据值)
        • 数据值⼀般不写, 默认是 None
      • 返回:
        • 如果键存在 返回键对应的数据值
        • 如果键不存在, 返回的是 括号中书写的数据值(None)
      • ⼀般建议使⽤ get ⽅法
  • 遍历:

    • 对键遍历
      • for 变量 in 字典: # 变量就是字典的 key, 键
      • for 变量 in 字典.keys(): # 字典.keys() 可以获取字典中所有的键
    • 对值遍历
      • for 变量 in 字典.values(): # 字典.values() 可以获取字典中所有的值
    • 对键值对遍历
      • # 变量1 就是 键, 变量2 就是键对应的值
      • for 变量1, 变量2 in 字典.items(): # 字典.items() 获取键值对

    # 1. 字符串, 列表, 元组 ⽀持加法运算

    str1 = ‘hello’ + ’ world’ # ‘hello world’

    list1 = [1, 2] + [3, 4] # [1, 2, 3, 4]

    tuple1 = (1, 2) + (3, 4) # (1, 2, 3, 4)

    # 2. 字符串 列表 元组 ⽀持 乘⼀个数字

    'hello ’ * 3 # ===> 'hello hello hello ’

    [1, 2] * 3 # ===> [1, 2, 1, 2, 1, 2]

    (1, 2) * 3 # ===> (1, 2, 1, 2, 1, 2)

    # 3. len() 在 容器中都可以使⽤

    # 4. in 关键字在容器中都可以使⽤, 注意, 在字典中判断的是字典的键是否存在

    列表去重:列表中存在多个数据, 需求, 去除列表中重复的数据.

    ⽅式1. 思路

    遍历原列表中的数据判断在新列表中是否存在, 如果存在,不管,

    如果不存在放⼊新的列表中

    遍历: for 循环实现

    判断是否存在: 可以 使⽤ in

    存⼊数据: append()

    ⽅法 2:

    在 Python 中还有⼀种数据类型(容器) ,称为是 集合(set)

    特点: 集合中不能有重复的数据(如果有重复的数据会⾃动去重)可以使⽤集合的特点对列表去重

    \1. 使⽤ set() 类型转换将列表转换为 集合类型

    \2. 再使⽤ list() 类型转换将集合 转换为列表

    缺点: 不能保证数据在原列表中出现的顺序(⼀般来说,也不考虑这件事)

2.4 集合

  • 概念:用来保存不重复的元素,即集合中的元素都是唯一的,无序的,互不相同。

  • 创建方式:

    • 1.set()函数
      • setname = set(iteration)
      • iteration 就表示字符串、列表、元组、range 对象等数据。
    • 2.{}
      • setname = {element1, element2, … , elementn}
    • 如果要创建空集合,只能使用 set() 函数实现。因为直接使用一对 {},Python 解释器会将其视为一个空字典。
    • 同一集合中,只能存储不可变的数据类型,包括整形、浮点型、字符串、元组,无法存储列表、字典、集合这些可变的数据类型
  • 访问方式:

    • 集合中元素是无序的,一般使用循环结构遍历
  • 删除集合:del()

  • 添加元素:setname.add(element)

  • 删除元素:setname.remove(element)

  • 运算:

    • 有 2 个集合,分别为 set1={1,2,3} 和 set2={3,4,5},它们既有相同的元素,也有不同的元素。以这两个集合为例,分别做不同运算的结果如下表所示。

      运算操作Python运算符含义例子
      交集&取两集合公共的元素>>> set1 & set2 {3}
      并集|取两集合全部的元素>>> set1 | set2 {1,2,3,4,5}
      差集-取一个集合中另一集合没有的元素>>> set1 - set2 {1,2}
      对称差集^取集合 A 和 B 中不属于 A&B 的元素>>> set1 ^ set2 {1,2,4,5}

3.面向对象

3.1 函数

  • 概念:

    • 函数,就是把 具有独⽴功能的代码块 组织为⼀个⼩模块,在需要的时候调⽤
    • 函数好处: 减少代码的冗余(重复的代码不⽤多写), 提⾼程序的编写效率
  • 定义:

    • 将多⾏代码放在⼀块,起名字的过程, 称为函数定义
    • 函数必须先定义后调⽤
  • 语法:

    def 函数名():
        函数中的代码
     	函数中的代码 
        
    # 1. def 是关键字, ⽤来定义函数的 define 的缩写
    # 2. 函数名需要遵守标识符的规则
    # 3. 处于 def 缩进中的代码,称为函数体
    # 4. 函数定义的时候, 函数体中的代码不会执⾏, 在调⽤的时候才会执⾏
    
    函数名()
    # 1. 函数调⽤的时候会执⾏函数体中代码
    # 2. 函数调⽤的代码,要写在 函数体外边
    
  • 文档注释:

      1. 书写位置, 在函数名的下⽅使⽤ 三对双引号进⾏的注释

      2. 作⽤: 告诉别⼈这个函数如何使⽤的, ⼲什么的

      3. 查看, 在调⽤的时候, 将光标放到函数名上,使⽤快捷键

  • 函数嵌套调用:

    • 在⼀个函数定义中调⽤另⼀个函数
      • 函数定义不会执⾏函数体中的代码
      • 函数调⽤会执⾏函数体中的代码
      • 函数体中代码执⾏结束会回到函数被调⽤的地⽅继续向下执⾏
  • 返回值:

    • 在函数中想要将⼀个数据作为返回值 返回, 需要使⽤ return关键字(只能在函数中使⽤)

    • 作⽤:

      • 将数据值作为返回值返回
      • 函数代码执⾏遇到 return, 会结束函数的执⾏
      • 将 多个数据值组成容器进⾏返回, ⼀般是元组(组包)
      def 函数名(): # 返回值 None
       	pass # 代码中没有 return
      def 函数名():
       	return # return 后边没有数据, 返回值 None
      def 函数名():
       	return xx # 返回值是 xx
      
  • 变量引用

      1. 在定义变量的时候 变量 = 数据值, Python 解释器会在内存中开辟两块空间

      2. 变量和数据都有⾃⼰的空间

      3. ⽇常简单理解, 将数据保存到变量的内存中, 本质是 将 数据的地址保存到变量对应的内存中

      4. 变量中存储数据地址的⾏为 就是引⽤ (变量引⽤了数据的地址, 简单说就是变量中存储数据), 存储的地址称为 引⽤地址

      5. 可以使⽤ id() 来获取变量中的引⽤地址(即数据的地址),如果两个变量的 id() 获取的引⽤地址⼀样, 即代表着, 两个变量引⽤了同⼀个数据,是同⼀个数据

      6. 只有 赋值运算符=, 可以改变变量的引⽤(等号左边数据的引⽤)

      7. python 中数据的传递,都是传递的引⽤

  • 可变类型和不可变类型:

    • 概念:数据所在的内存是否允许修改, 允许修改就是可变类型, 不允许修改就是不可变类型
    • 可变类型:列表 list, 字典 dict, 集合 set
    • 不可变类型:int float bool str tuple
  • 组包和拆包:

    • 组包(pack): 将多个数据值使⽤逗号连接, 组成元组
    • 拆包(unpack): 将容器中的数据值使⽤多个变量分别保存的过程,注意: 变量的个数和容器中数据的个数要保持⼀致
    • 赋值运算符, 都是先执⾏等号右边的代码, 执⾏的结果,保存到等号左边的变量中
    # 组包
    c = b, a # 组包
    print(type(c), c) # <class 'tuple'> (10, 20)
    # 拆包
    a, b = c
    print(a, b)
    x, y, z = [1, 2, 3]
    print(x, y, z)
    
  • 局部变量和全局变量:

    • 局部变量:
      • 在函数内部(函数的缩进中)定义的变量,称为是局部变量
      • 特点:
        • 局部变量只能在当前函数内部使⽤, 不能在其他函数和函数外部使⽤
        • 在不同函数中,可以定义名字相同的局部变量, 两者之间没有影响
        • ⽣存周期(⽣命周期, 作⽤范围)–> 在哪 能⽤在函数被调⽤的时候,局部变量被创建, 函数调⽤结束, 局部变量的值被销毁(删除), 不能使⽤
        • 所以函数中的局部变量的值, 如果想要在函数外部使⽤, 需要使⽤ return 关键字, 将这个值进⾏返回
    • 全局变量:
      • 定义位置: 在函数外部定义的变量, 称为是 全局变量
      • 特点:
        • 可以在任何函数中读取(获取) 全局变量的值
        • 如何在函数中存在和全局变量名字相同的局部变量, 在函数中使⽤的是 局部变量的值(就近)
        • 在函数内部想要修改全局变量的引⽤(数据值), 需要添加global 关键字, 对变量进⾏声明为全局变量
        • ⽣命周期: 代码执⾏的时候被创建, 代码执⾏结束,被销毁(删除)
  • 函数参数:

    • 位置传参:在函数调⽤的时候, 按照形参的顺序, 将实参值传递给形参
    • 关键字传参:在函数调⽤的时候, 指定数据值给到那个形参
    • 混合使用:
      • 关键字传参必须写在位置传参的后⾯
      • 不要给⼀个形参传递多个数据值
    def func(a, b, c):
        print(f'a: {a}, b: {b}, c: {c}')
    # 位置传参
    func(1, 2, 3)
    # 关键字传参
    func(a=2, b=3, c=1)
    # 混合使⽤
    func(1, 3, c=5)
    
  • 缺省参数(默认参数:

    • 定义⽅式
      • 在函数定义的时候, 给形参⼀个默认的数据值, 这个形参就变为缺省参数, 注意, 缺省参数的书写要放在普通参数的后边
    • 特点(好处)
      • 缺省参数, 在函数调⽤的时候, 可以传递实参值, 也可以不传递实参值
      • 如果传参,使⽤的就是传递的实参值, 如果不传参,使⽤的就是默认值
    def show_info(name, sex='保密'):
        print(name, sex)
    show_info('⼩王')
    show_info('⼩王', '男')
    
  • 多值参数:

    • 不定长位置参数(元组
      • 书写, 在普通参数的前边,加上⼀个 *, 这个参数就变为不定⻓位置参数
      • 特点, 这个形参可以接收任意多个 位置传参的数据
      • 数据类型, 形参的类型是 元组
      • 注意, 不定⻓位置参数 要写在普通的参数的后⾯
      • ⼀般写法, 不定⻓位置参数的名字为 args, 即(*args) # arguments
    • 不定长关键字参数(字典
      • 书写, 在普通参数的前边,加上 两个 *, 这个参数就变为不定⻓关键字参数
      • 特点, 这个形参可以接收任意多个 关键字传参的数据
      • 数据类型, 形参的类型是 字典
      • 注意, 不定⻓关键字参数,要写在所有参数的最后边
      • ⼀般写法, 不定⻓关键字参数的名字为 kwargs,即(**kwargs), keyword arguments
    def 函数名(普通函数, *args, 缺省参数, **kwargs):
     	pass
    # ⼀般在使⽤的时候, 使⽤ 1-2种, 按照这个顺序挑选书写即可
    
    def func(*args, **kwargs):
     	print(type(args), args)
     	print(type(kwargs), kwargs)
     	print('-' * 30)
    func()
    func(1, 2, 3) # 位置传参, 数据都给 args
    func(a=1, b=2, c=3) # 关键字传参, 数据都给 kwargs
    func(1, 2, 3, a=4, b=5, c=6)
    
  • 匿名函数:

    • 概念:就是使⽤ lambda 关键字定义的函数
      • ⼀般称为使⽤def 关键字定义的函数为, 标准函数
    • 特点:
      • 匿名函数只能书写⼀⾏代码
      • 匿名函数的返回值不需要 return, ⼀⾏代码(表达式) 的结果就是返回值
    • 使⽤场景: 作为函数的参数, 这个函数⽐较简单,值使⽤⼀次,没有必要使⽤ def 定义
    • 语法:
      • lambda 参数: ⼀⾏代码 # 这⼀⾏代码,称为是表达式
      • 变量 = lambda 参数: ⼀⾏代码 #使用变量进行调用变量()

3.2 面向对象

  • ⾯向对象是⼀个编程思想(写代码的套路)

  • 编程思想:

    • ⾯向过程
      • 关注的是 具体步骤的实现, 所有的功能都⾃⼰书写,亲⼒亲为
      • 定义⼀个个函数, 最终按照顺序调⽤函数
    • ⾯向对象
      • 关注的是结果, 谁(对象) 能帮我做这件事偷懒
      • 找⼀个对象(), 让对象去做
  • 类和对象:

      • 抽象的概念, 对 多个 特征和⾏为相同或者相似事物的统称
      • 泛指的(指代多个,⽽不是具体的⼀个)
    • 对象
      • 具体存在的⼀个事物, 看得⻅摸得着的
      • 特指的,(指代⼀个)
  • 类的组成:

    • 类名 (给这多个事物起⼀个名字, 在代码中 满⾜⼤驼峰命名法(每个单词的⾸字⺟⼤写))
    • 属性 (事物的特征, 即有什么, ⼀般⽂字中的名词)
    • ⽅法 (事物的⾏为, 即做什么事, ⼀般是动词)
  • 面向对象基本代码:

    • 1.定义类:

      class 类名:
          # 在缩进中书写的内容,都是类中的代码
       	def ⽅法名(self): # 就是⼀个⽅法
              pass
      
    • 2.创建对象

      类名() # 创建⼀个对象, 这个对象在后续不能使⽤
      # 创建的对象想要在后续的代码中继续使⽤, 需要使⽤⼀个变量,将这个对象保存起来
      变量 = 类名() # 这个变量中保存的是对象的地址, ⼀般可以成为这个变量为对象
      # ⼀个类可以创建多个对象, 只要出现 类名() 就是创建⼀个对象,每个对象的地址是不⼀样的
      
    • 示例代码:

    class Cat:
        # 在缩进中书写 ⽅法
        def eat(self): # self 会⾃动出现,暂不管
            print('⼩猫爱吃⻥...')
        def drink(self):
     	print('⼩猫要喝⽔----')
    # 2. 创建对象
    blue_cat = Cat()
    # 3. 通过对象调⽤类中的⽅法
    blue_cat.eat()
    blue_cat.drink()
    # 创建对象
    black_cat = Cat()
    black_cat.eat()
    black_cat.drink()
    Cat() # 是
    a = black_cat # 不是
    b = Cat # 不是
    -----self-------
    1. 从函数的语法上讲, self是形参, 就可以是任意的变量名,只不过我们习惯性将这个形参写作 self
    2. self 是普通的形参, 但是在调⽤的时候没有传递实参值,原因是, Python 解释器在执⾏代码的时候, ⾃动的将调⽤这个⽅法的对象 传递给了 self, 即 self 的本质是对象
    3. 验证, 只需要确定 通过哪个对象调⽤, 对象的引⽤和 self的引⽤是⼀样的
    4. self 是函数中的局部变量, 直接创建的对象是全局变量
    //有点像this,指代当前对象
    
  • 对象属性操作:

    • 添加属性:对象.属性名 = 属性值
      • 类内部添加:
        • self.属性名 = 属性值
        • 在类中添加属性⼀般写在 init ⽅法中
      • 类外部添加:
        • 对象.属性名 = 属性值 # ⼀般不使⽤
    • 获取属性:对象.属性名
      • 类内部:
        • self.属性名
      • 类外部:
        • 对象.属性名 # ⼀般很少使⽤

3.3 魔法方法

  • 概念:

    • python 中有⼀类⽅法, 以两个下划线开头,两个下划线结尾,并且在满⾜某个条件的情况下, 会⾃动调⽤, 这类⽅法称为 魔法方法
  • _init_ ⽅法:

    • 创建对象之后会⾃动调⽤
    • 给对象添加属性的, (初始化⽅法, 构造⽅法)
    • 某些代码, 在每次创建对象之后, 都要执⾏,就可以将这⾏代码写在 init ⽅法
    • 如果 init ⽅法中,存在除了 self之外的参数, 在创建对象的时候必须传参
    class Cat:
     # 定义添加属性的⽅法
     	def __init__(self, name, age): # 这个⽅法是创建对象之后调⽤
     		self.name = name # 给对象添加 name 属性
     		self.age = age # 给对象添加 age 属性
     # 输出属性信息
    	def show_info(self):
     		print(f'⼩猫的名字是: {self.name}, 年龄是:{self.age}')
    # 创建对象,不要在⾃⼰类缩进中创建
    # Cat() # 创建对象 ,会输出
    blue_cat = Cat('蓝猫', 2)
    blue = blue_cat
    blue.show_info()
    # 创建⿊猫
    black_cat = Cat('⿊猫', 3)
    black_cat.show_info()
    
  • __str__方法

    • 使⽤ print(对象) 打印对象的时候 会⾃动调⽤
    • 在这个⽅法中⼀般书写对象的 属性信息的, 即打印对象的时候想要查看什么信息,在这个⽅法中进⾏定义的
    • 如果类中没有定义 str ⽅法, print(对象) ,默认输出对象的引⽤地址
    • 这个⽅法必须返回 ⼀个字符串
    class Cat:
     # 定义添加属性的⽅法
     	def __init__(self, n, age): # 这个⽅法是创建对象之后调⽤
     		self.name = n # 给对象添加 name 属性
    		self.age = age # 给对象添加 age 属性
    	def __str__(self):
     # ⽅法必须返回⼀个字符串, 只要是字符串就⾏,
     		return f'⼩猫的名字是: {self.name}, 年龄是:{self.age}'
    # 创建对象,不要在⾃⼰类缩进中创建
    # Cat() # 创建对象 ,会输出
    blue_cat = Cat('蓝猫', 2)
    print(blue_cat)
    # 创建⿊猫
    black_cat = Cat('⿊猫', 3)
    print(black_cat)
    
  • __del__方法

    • _init_ ⽅法, 创建对象之后,会⾃动调⽤ (构造⽅法)
    • _del_ ⽅法, 对象被删除销毁时, ⾃动调⽤的(遗⾔, 处理后事) (析构⽅法)
    • 调⽤场景, 程序代码运⾏结束, 所有对象都被销毁
    • 调⽤场景, 直接使⽤ del 删除对象(如果对象有多个名字(多个对象引⽤⼀个对象),需要吧所有的对象都删除才⾏ )

3.4 封装继承多态

  • 私有和公有

    1. 在 Python 中定义的方法和属性, 可以添加访问控制权限(即在什么地方可以使用这个属性和方法)

    2. 访问控制权限分为两种, 公有权限, 私有权限

    3. 公有权限

      1. 直接书写的方法和属性, 都是公有的
      2. 公有的方法和属性, 可以在任意地方访问和使用
    4. 私有权限

      1. 在类内部, 属性名或者方法名 前边加上两个 划线 , 这个属性或者方法 就变为 私有的
      2. 私有的方法和属性, 只能在当前类的内部使用
    5. 什么时候定义私有

      1. 某个属性或者方法,不想在类外部被访问和使用, 就将其定义为私有即可

      2. 测试中,一般不怎么使用, 直接公有即可

      3. 开发中,会根据需求文档, 确定什么作为私有

    6. 如果想要在类外部操作私有属性, 方法是, 在类内部定义公有的方法, 我们通过这个公有方法去操作

    # 补充:

    # 对象.dict 魔法属性, 可以将对象具有的属性组成字典返回

    class Person:
    	def __init__(self, name, age):
    		self.name = name # 姓名
    # 私有的本质, 是 Python 解释器执行代码,发现属性名或者方法名前有两个_, 会将这个名字重命名
    # 会在这个名字的前边加上 _类名前缀,即 self.__age ===> self._Person__age
    		self.__age = age # 年龄, 将其定义为私有属性, 属性名前加上两个 _
    	def __str__(self): # 在类内部可以访问私有属性的
    		return f'名字: {self.name}, 年龄: {self.__age}'
    xm = Person('小明', 18)
    print(xm)
    # 在类外部直接访问 age 属性
    # print(xm.__age) # 会报错, 在类外部不能直接使用私有属性
    # 直接修改 age 属性
    xm.__age = 20 # 这个不是修改私有属性, 是添加了一个公有的属性 __age
    print(xm) # 名字: 小明, 年龄: 18
    print(xm._Person__age) # 能用但是不要用 18
    xm._Person__age = 19
    print(xm) # 名字: 小明, 年龄: 19
    
  • 继承:

      1. 继承描述的是类与类之间的关系

      2. 继承的好处: 减少代码的冗余(相同的代码不需要多次重复书写), 可以直接使用

        # class A(object):
        class A: # 没有写父类,但也有父类, object, object 类是 Python 中最顶级(原始)的类
        	pass
        class B(A): # 类 B, 继承类 A
            pass
        -------------
        术语:
        1. A 类, 称为是 父类(基类)
        2. B 类, 称为是 子类(派生类)
        单继承: 一个类只继承一个父类,称为单继承
        继承之后的特点:
        > 子类(B)继承父类(A)之后, 子类的对象可以直接使用父类中定义的公有属性和方法
        
  • 重写:

    • 重写: 在子类中定义了和父类中名字相同的方法, 就是重写

    • 重写的原因: 父类中的方法,不能满足子类对象的需求,所以重写

    • 重写之后的特点: 调用子类字节的方法, 不再调用父类中的方法

    • 重写的方式:

      1. 覆盖(父类中功能完全抛弃,不要,重写书写)

        1. 直接在子类中 定义和父类中名字相同的方法
        2. 直接在方法中书写新的代码
      2. 扩展(父类中功能还调用,只是添加一些新的功能) (使用较多)

        1. 直接在子类中 定义和父类中名字相同的方法
        2. 在合适的地方调用 父类中方法 super().方法()
        3. 书写添加的新功能
  • 多态:

      1. 是一种写代码,调用的一种技巧

      2. 同一个方法, 传入不同的对象, 执行得到不同的结果, 这种现象称为是多态

      3. 多态 可以 增加代码的灵活度

      --------

      哪个对象调用方法, 就去自己的类中去查找这个方法, 找不到去父类找

  • 对象划分:

    • 实例对象:

      1. 通过 类名() 创建的对象, 我们称为实例对象,简称实例

      2. 创建对象的过程称为是类的实例化

      3. 我们平时所说的对象就是指 实例对象(实例)

      4. 每个实例对象, 都有自己的内存空间, 在自己的内存空间中保存自己的属性(实例属性)

    • 类对象:

      1. 类对象 就是 类, 或者可以认为是 类名

      2. 类对象是 Python 解释器在执行代码的过程中 创建的

      3. 类对象的作用: ① 使用类对象创建实例 类名(), ② 类对象 也有自己的内存空间, 可以保存一些属性值信息(类属性)

      4. 在一个代码中, 一个类 只有一份内存空间

  • 属性划分:

    • 实例属性:是实例对象 具有的属性
      • 定义使用:
        • 在 init 方法中, 使用 self.属性名 = 属性值 定义
        • 在方法中是 使用 self.属性名 来获取(调用)
    • 类属性:是 类对象 具有的属性
      • 定义使用:
        • 在类内部,方法外部,直接定义的变量 ,就是类属性
        • 使用: 类对象.属性名 = 属性值 or 类名.属性名 = 属性值
        • 类对象.属性名 or 类名.属性名
  • 方法划分:

    • 实例方法:

      • 定义:

        # 在类中直接定义的方法 就是 实例方法
        class Demo:
        	def func(self): # 参数一般写作 self,表示的是实例对象
        		pass
        # 如果在方法中需要使用实例属性(即需要使用 self), 则这个方法必须定义为 实例方法
        
      • 调用:对象.方法名() #不用给self参

    • 类方法:

      • 定义:

        # 在方法名字的上方书写 @classmethod 装饰器(使用 @classmethod 装饰的方法)
        class Demo:
        	@classmethod
        	def func(cls): # 参数一般写作 cls, 表示的是类对象(即类名) class
        		pass
        
      • 调用:

        • 类名.方法名()
        • 实例.方法名()
    • 静态方法(基本不用:

      • 定义:

        # 在方法名字的上方书写 @staticmethod 装饰器(使用 @staticmethod 装饰的方法)
        class Demo:
        	@staticmethod
        	def func(): # 一般没有参数
        		pass
        
      • 调用:

        • # 1. 通过类对象调用

          类名.方法名()

          # 2. 通过实例对象调用

          实例.方法名()

  • 补充:

    • is 可以用来判断两个对象是不是同一个对象,即 两个对象的引用是否相同
      • a is b === > id(a) == id(b)
      • is 和 == 的区别?
        • == 只判断数据值是否相同, is 判断引用是否相同

4.文件

4.1 普通文件

  • 文件分类:

    • 文本文件
      • 能够使⽤记事本软件打开(能够使⽤记事本转换为⽂字)
      • txt, md, py , html, css, js , json
    • 二进制文件
      • 不能使⽤记事本软件打开的
      • exe, mp3, mp4, jpg, png
  • 文件操作:

      1. 打开⽂件

      2. 读或者写⽂件

      3. 关闭⽂件

  • 打开文件

    • 打开⽂件: 将⽂件从磁盘(硬盘) 中 读取到内存中
    • 语法:open(file, mode=‘r’, encoding=None)
      • 参数 file: 是要打开的⽂件, 类型是字符串, ⽂件的路径可以是相对路径,也可以是绝对路径(从根⽬录开始书写的路径),建议使⽤相对路径(相对于当前代码⽂件所在的路径, ./…/ )
      • 参数 mode: 默认参数(缺省参数), 表示的是打开⽂件的⽅式
        • r: read 只读打开
        • w: write 只写打开
        • a: append 追加打开, 在⽂件的末尾写⼊内容
      • 参数 encoding: 编码⽅式,(⽂字和⼆进制如何进⾏转换的)
        • gbk: 将⼀个汉字转换为 2 个字节⼆进制
        • utf-8: 常⽤, 将⼀个汉字转换为 3 个字节的⼆进制
      • 返回值: 返回的是 ⽂件对象, 后续对⽂件的操作,都需要这个对象
  • 读或写文件

    • 写文件:
      • 向⽂件中写⼊指定的内容。前提: ⽂件的打开⽅式是 w 或者 a
      • ⽂件对象.write(‘写⼊⽂件的内容’)
        • 返回值: 写⼊⽂件的字符数,⼀般不关注
        • 注意 w ⽅式打开⽂件:
          • ⽂件不存在,会直接创建⽂件
          • ⽂件存在,会覆盖原⽂件(将原⽂件中的内容清空)
    • 读文件:
      • 将⽂件中的内容读取出来,前提: ⽂件的打开⽅式需要是 r
      • ⽂件对象.read(n)
        • 参数 n 表示读取多少个字符, ⼀般不写,表示读取全部内容
        • 返回值: 读取到的⽂件内容, 类型 字符串
  • 关闭文件

    • 关闭⽂件: 将⽂件占⽤的资源进⾏清理,同时会保存⽂件, ⽂件关闭之后,这个⽂件对象就不能使⽤了
    • ⽂件对象.close()
  • with open打开文件

    • with open() 打开⽂件的好处: 不⽤⾃⼰去书写关闭⽂件的代码, 会⾃动进⾏关闭

    • with open(file, mode, encoding=‘utf-8’) as 变量:

      # 在缩进中去读取或者写⼊⽂件

      # 缩进中的代码执⾏结束, 出缩进之后, ⽂件会⾃动关闭

  • 按行读取文件内容

    • 按⾏读取⽂件: ⼀次读取⼀⾏内容
    • ⽂件对象.readline()
    # read() 和 readline() 读到⽂件末尾, 返回⼀个空字符串,即⻓度为 0
    # 在容器中 , 容器为空,即容器中的数据的个数为 0 ,表示False, 其余情况都是 True
    with open('b.txt', encoding='utf-8') as f:
     	while True:
     		buf = f.readline()
     		if len(buf) == 0:
     			break
     		else:
     			print(buf, end='')
    

4.2 json文件

  • 基本介绍:

    • json 基于⽂本,独⽴于语⾔的轻量级的数据交换格式

      - 基于⽂本, 是⼀个⽂本⽂件, 不能包含图⽚,⾳视频等

      - 独⽴于语⾔, 不是某个语⾔特有的, 每种编程语⾔都可以使⽤

      - 轻量级, 相同的数据, 和其他格式相⽐,占⽤的⼤⼩⽐较⼩

      - 数据交换格式, 后端程序员 给前端的数据 (json, html,xml)

  • json文件语法:

      1. json ⽂件的后缀是 .json

      2. json 中主要数据类型为 对象({} 类似 Python 中 字典)和 数组([], 类似 Python 中的列表), 对象和 数组可以互相嵌套

      3. ⼀个json ⽂件是⼀个 对象或者数组(即 json ⽂件的最外层要么是⼀个 {}, 要么是⼀个 数组 [])

      4. json 中的对象是由键值对组成的, 每个数据之间使⽤ 逗号隔开,但是最后⼀个数据后边不要写逗号

      5. json 中的字符串 必须使⽤ 双引号

      6. json 中的其他数据类型

      > 数字类型 ----> int float

      > 字符串 string —> str

      > 布尔类型 true, false -----> True, False

      > 空类型 null ----> None

  • json文件书写:

    • 我叫⼩明,我今年 18 岁,性别男, 爱好 听歌, 游戏,购物,吃饭,睡觉,打⾖⾖,我的居住地址为 国家中国, 城市上海

      {
          "name": "⼩明",
          "age": 18,
          "isMen": true,
          "like": [
              "听歌",
              "游戏",
              "购物",
              "吃饭",
              "睡觉",
              "打⾖⾖"
          ],
          "address": {
              "country": "中国",
              "city": "上海"
          }
      }
      
  • python读取json文件

      1. 导包 import json

      2. 读打开⽂件

      3. 读⽂件

        json.load(⽂件对象)

      # 返回的是 字典(⽂件中是对象)或者列表(⽂件中是数组)

      # 1, 导⼊ json
      import json
      # 2, 读打开⽂件
      with open('info.json', encoding='utf-8') as f:
          # 3. 读取⽂件
          result = json.load(f)
          print(type(result)) # <class 'dict'>
          # 姓名
          print(result.get('name'))
          # 年龄
          print(result.get('age'))
          # 城市
          print(result.get('address').get('city'))
      
  • json写入文件

    • ⽂件对象.write(字符串) 不能直接将 Python 的列表 和字典作为参数传递

    • 想要将 Python 中的数据类型存为 json ⽂件, 需要使⽤ json提供的⽅法, 不再使⽤ write

    • 步骤:

      1. 导包 import json

      2. 写(w) ⽅式打开⽂件

      3. 写⼊ json.dump(Python 中的数据类型, ⽂件对象)

    import json
    my_list = [('admin', '123456', '登录成功'), ('root','123456', '登录失败'), ('admin', '123123', '登录失败')]
    with open('info4.json', 'w', encoding='utf-8') as f:
        # json.dump(my_list, f)
        # json.dump(my_list, f, ensure_ascii=False) #直接显示中⽂,不以 ASCII 的⽅式显示
        # 显示缩进
        # json.dump(my_list, f, ensure_ascii=False,indent=2)
        json.dump(my_list, f, ensure_ascii=False,indent=4)
    

5.异常

  • 异常捕获基本语法:

    try:
        书写可能发⽣异常的代码
    except: # 任何类型的异常都能捕获
         发⽣了异常执⾏的代码
    
    
    try:
    	书写可能发⽣异常的代码
    except 异常类型: # 只能捕获指定类型的异常, 如果不是这个异常,还是会报错
        发⽣了异常执⾏的代码
    ------------------------
    try:
         书写可能发⽣异常的代码
    except 异常类型1: # 只能捕获指定类型的异常, 如果不是这个异常,还是会报错
         发⽣了异常1执⾏的代码 
    except 异常类型2:
         发⽣了异常2执⾏的代码 
    except 异常类型...:
         发⽣了异常...执⾏的代码
    -----------------
    try:
         可能发⽣异常的代码
    except 异常类型1:
         发⽣异常类型1执⾏的代码
    # Exception 是常⻅异常类的⽗类, 这⾥书写 Exception,可以捕获常⻅的所有异常, as 变量, 这个变量是⼀个异常类的对象, print(变量) 可以打印异常信息 
    except Exception as 变量: 
         发⽣其他类型的异常,执⾏的代码
    else:
         没有发⽣异常会执⾏的代码
    finally:
         不管有没有发⽣异常,都会执⾏的代码
    
  • 模块和包

    • 导入方式

      • import 模块名

        # 使⽤模块中的内容

        模块名.⼯具名

      • from 模块名 import ⼯具名

        # 使⽤

        ⼯具名 # 如果是函数和类需要加括号

      • from 模块名 import * # 将模块中所有的内容都导⼊

    • 对于导⼊的模块和⼯具可以使⽤ as 关键字给其起别名,注意: 如果起别名,原来的名字就不能⽤了, 只能使⽤别名

    • 模块查找顺序:当前目录-》系统目录

  • __name__作用

    • 每个代码⽂件都是⼀个模块,在导⼊模块的时候, 会执⾏模块中的代码(三种⽅法都会)

    • _name_ 变量 是 python 解释器⾃动维护的变量

    • __name__ 变量,如果代码是直接运⾏, 值是 “__main__”

    • _name_ 变量, 如果代码是被导⼊执⾏, 值是 模块名(即代码⽂件名)

      在代码⽂件中, 在被导⼊时不想被执⾏的代码,可以写在 if__name__ == “__main__”: 代码的缩进中

6.Unittest

6.1 Unitttest

  • 概念:UnitTest是Python⾃带的⼀个单元测试框架,⽤它来做单元测试。

  • 优点:

      1. 能够组织多个⽤例去执⾏

      2. 提供丰富的断⾔⽅法(让程序代码代替⼈⼯⾃动的判断预期结果和实际结果是否相符)

      3. 能够⽣成测试报告

  • 组成部分

    • TestCase(最核⼼的模块)
      • TestCase(测试⽤例), 注意这个测试⽤例是 unittest 框架的组成部分
      • 主要作⽤: 每个 TestCase(测试⽤例) 都是⼀个代码⽂件, 在这个代码⽂件中 来书写真正的⽤例代码
    • TestSuite
      • TestSuite(测试套件), ⽤来 管理 组装(打包)多个TestCase(测试⽤例) 的
    • TestRunner
      • TestRunner(测试执⾏,测试运⾏), ⽤来 执⾏TestSuite(测试套件)的
    • TestLoader
      • TestLoader(测试加载), 功能是对 TestSuite(测试套件) 功能的补充,管理 组装(打包)多个 TestCase(测试⽤例) 的
    • Fixture
      • Fixture(测试夹具), 书写在 TestCase(测试⽤例) 代码中, 是⼀个代码结构, 可以在每个⽅法执⾏前后都会执⾏的内容
  • TestCase(测试用例)

    • 步骤:

        1. 导包(unittest)
        2. 自定义测试类
        3. 测试类中书写测试方法
        4. 执行用例
        # 1, 导包
        import unittest
        # 2, ⾃定义测试类, 需要继承 unittest 模块中的TestCase 类即可
        class TestDemo(unittest.TestCase):
            # 3, 书写测试⽅法, 即 ⽤例代码. ⽬前没有真正的⽤例代码, 使⽤ print 代替
            # 书写要求, 测试⽅法 必须以 test_ 开头(本质是以test 开头)
            def test_method1(self):
                print('测试⽅法 1')
            def test_method2(self):	
                print('测试⽅法 2')
                # 4, 执⾏⽤例(⽅法)
                # 4.1 将光标放在 类名的后边 运⾏, 会执⾏类中的所有的测试⽅法
                # 4.2 将光标放在 ⽅法名的后边 运⾏, 只执⾏当前的⽅法
        
  • TestSuite(测试套件) & TsetRunner(测试执行)

    • 步骤:

        1. 导包(unittest)

        2. 实例化(创建对象)套件对象

        3. 使⽤套件对象添加⽤例⽅法

        4. 实例化运⾏对象

        5. 使⽤运⾏对象去执⾏套件对象

        # 1. 导包(unittest)
        import unittest
        from hm_07_testcase1 import TestDemo1
        from hm_07_testcase2 import TestDemo2
        # 2. 实例化(创建对象)套件对象,
        suite = unittest.TestSuite()
        # 3. 使⽤套件对象添加⽤例⽅法
        # ⽅式⼀, 套件对象.addTest(测试类名('⽅法名')) #建议测试类名和⽅法名直接去复制,不要⼿写
        suite.addTest(TestDemo1('test_method1'))
        suite.addTest(TestDemo1('test_method2'))
        # ⽅式⼆ 将⼀个测试类中的所有⽅法进⾏添加
        suite.addTest(unittest.makeSuite(TestDemo2))
        
        # 4. 实例化运⾏对象
        runner = unittest.TextTestRunner()
        # 5. 使⽤运⾏对象去执⾏套件对象
        # 运⾏对象.run(套件对象)
        runner.run(suite)
        
  • TestLoader(测试加载)

    • 概念:TestLoader (测试加载), 作用和 TestSuite 的作用是一样的, 对 TestSuite 功能的补充,用来组装测试用例的

    • 步骤:

        1. 导包
        2. 实例化测试加载对象并添加用例 —> 得到的是 suite 对象
        3. 实例化 运行对象
        4. 运行对象执行套件对象
        """TestLoader 的使用"""
        # 1, 导包
        import unittest
        # 2, 实例化加载对象并添加用例
        # unittest.TestLoader().discover('用例所在的路径', '用例的代码文件名')
        # 用例所在的路径,建议使用相对路径, 用例的代码文件名可以使用 *(任意多个任意字符) 通配符
        suite = unittest.TestLoader().discover('./case', '*case1.py')
        # 3, 实例化运行对象
        # runner = unittest.TextTestRunner()
        # # 4, 执行
        # runner.run(suite)
        # 可以将 3 4 步 变为一步
        unittest.TextTestRunner().run(suite)
        
  • Fixture(测试夹具)

    • 概念:在每个测试方法(用例代码)、测试类、测试模块 执行前后都会自动调用的结构

    • 方法级别:

      # 方法执行之前--c
      def setUp(self):
          每个测试方法执行之前都会执行
          pass
      # 方法执行之后--销毁
      def tearDown(self):
          每个测试方法执行之后都会执行
          pass
      
    • 类级别:

      # 类级别的Fixture 方法, 是一个 类方法
      # 类中所有方法之前
      @classmethod
      def setUpClass(cls):
          pass
      # 类中所有方法之后
      @classmethod
      def tearDownClass(cls):
          pass
      
    • 模块级别:

      # 模块级别的需要写在类的外边直接定义函数即可
      # 代码文件之前
      def setUpModule():
          pass
      # 代码文件之后
      def tearDownModule():
          pass
      

6.2 断言

  • 概念:让程序代替人工自动的判断预期结果和实际结果是否相符.

  • 断言的结果有两种:

    > True, 用例通过

    > False, 代码抛出异常, 用例不通过

  • assertEqual:

    • self.assertEqual(预期结果, 实际结果) # 判断预期结果和实际结果是否相等

      1. 如果相等, 用例通过

      2. 如果不相等,用例不通过, 抛出异常

  • assertIn:

    • self.assertIn(预期结果, 实际结果) # 判断预期结果是否包含在实际结果中

      1. 包含 ,用例通过

      2. 不包含, 用例不通过, 抛出异常

  • 参数化:

    • 概念:在测试方法中, 使用 变量 来代替具体的测试数据, 然后使用传参的方法将测试数据传递给方法的变量好处: 相似的代码不需要多次书写.

    • 工作中场景:

      1. 测试数据一般放在 json 文件中

      2. 使用代码读取 json 文件,提取我们想要的数据 —> [(), ()] or [[], []]

    • 安装插件

      • unittest 框架本身是不支持 参数化, 想要使用参数化,需要安装插件来完成

        - 联网安装(在 cmd 窗口安装 或者 )

        pip install parameterized

    • 参数化代码

        1. 导包 unittest/ paramaterized

        2. 定义测试类

        3. 书写测试方法(用到的测试数据使用变量代替)

        4. 组织测试数据并传参

      json文件
      [
          {
              "desc": "正确的用户名和密码",
              "username": "admin",
              "password": "123456",
              "expect": "登录成功"
          },
          {
              "desc": "错误的的用户名",
              "username": "root",
              "password": "123456",
              "expect": "登录失败"
          },
          {
              "desc": "错误的的密码",
              "username": "admin",
              "password": "123123",
              "expect": "登录失败"
          }
      ]
      -------------------------
      # 1.导包unittest/ pa
      import json
      import unittest
      from parameterized import parameterized
      from tools import login
      # 组织测试数据 [(), (), ()] or [[], [], []]
      def build_data():
          with open('data.json', encoding='utf-8') as f:
              result = json.load(f) # [{}, {}, {}]
              data = []
              for i in result: # i {}
                  data.append((i.get('username'), i.get('password'), =i.get('expect')))
              return data
          # 2. 定义测试类
      class TestLogin(unittest.TestCase):
          # 3. 书写测试方法(用到的测试数据使用变量代替)
          @parameterized.expand(build_data())
          def test_login(self, username, password, expect):
              self.assertEqual(expect, login(username, password))
              # 4. 组织测试数据并传参(装饰器 @
      
  • 跳过:

    • 对于一些未完成的或者不满足测试条件的测试函数和测试类, 不想执行,可以使用跳过使用方法, 装饰器完成,代码书写在 TestCase 文件
    • @unittest.skip(‘跳过原因’) # 直接将测试函数标记成跳过
    • @unittest.skipIf(判断条件, ‘跳过原因’) # 根据条件判断测试函数是否跳过 , 判断条件成立, 跳过
  • 16
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python笔记.md 是一个用于记录Python编程相关内容的markdown文档。 在Python学习过程中,学习者通常会遇到各种问题和疑惑,需要有一个地方来记录学习笔记和重要概念,以方便日后复习和查阅。Python笔记.md 就是一个很好的选择。 Python笔记.md 可以按照自己的需要来组织内容,比如可以分为不同的章节或主题,并使用markdown语法来格式化文档,使其更加清晰易读。 在Python笔记.md中,可以记录Python的基础语法、常用数据结构、函数、类、模块等内容。此外,还可以记录一些常见的错误和解决方法,以便日后遇到类似问题时能够快速找到解决方案。 Python笔记.md 还可以用来记录自己的思考和理解。在学习过程中,我们常常会思考某个概念或代码背后的原理,这时候可以将自己的思考记录在笔记中,以便后续复习和回顾。 使用Python笔记.md 还可以方便与他人分享学习心得。可以在文档中加入注释或标题,使得文档更加易读和友好。同时,也可以将Python笔记.md 推送到版本控制系统中,与他人共享和共同编辑。 总之,Python笔记.md 是一个非常有用的工具,可以帮助学习者系统地记录、整理和复习Python编程相关的知识和经验。无论是初学者还是有经验的开发者,都可以从中受益,并提高自己的编程技能。 ### 回答2: Python笔记.md是一个使用Markdown语法编写的Python笔记文档。Markdown语法是一种轻量级的标记语言,可以快速地编辑和排版文档。 在Python笔记.md中,可以记录Python程序设计的相关知识、概念和技巧。通过使用Markdown语法,可以方便地插入代码块、链接、图片以及其他强调和排版格式,使得笔记更加直观和易读。 Python笔记.md可以按照不同的章节和主题组织内容,方便快速查找和阅读。在每个章节中,可以记录不同的Python编程概念,如数据类型、控制结构、函数、类等。可以通过示例代码和解释说明来详细解释这些概念的用法和特点。 在笔记中,还可以记录一些Python的常见问题和解决方案,例如常见错误、调试技巧等。这些内容可以帮助初学者更好地理解和掌握Python语言。 此外,Python笔记.md还可以连接到其他的Python资源,如官方文档、教程、在线代码编辑器等。这样可以提供更多的学习和参考资料。 总之,Python笔记.md是一个有条理、易读和方便编辑的Python学习笔记文档,可以帮助人们更好地学习和理解Python编程语言。 ### 回答3: Python笔记md是一种用来记录Python编程语言相关内容的文本文件格式。它使用Markdown语法来快速、简洁地编写和格式化笔记Python笔记md的优点是: 1. 简单易懂:Markdown语法简洁明了,使用起来非常简单,即便没有编程背景的人也能快速上手。 2. 跨平台兼容:无论是在Windows、Mac还是Linux系统中,Python笔记md都可以轻松使用。 3. 可读性强:Python笔记md的文本格式使得代码和说明可以同时显示,方便读者理解和学习。 4. 方便分享和发布:Python笔记md可以导出为HTML或PDF格式,方便分享给其他人或者发布到网络上。 5. 与开发工具兼容:大多数集成开发环境(IDE)和文本编辑器都支持Markdown语法,可以实时预览和编辑笔记。 使用Python笔记md可以帮助程序员记录代码和相关的解释和说明,方便复习和查看。它还可以用于编写技术博客、文档和教育材料等。而且由于其文本格式的特点,Python笔记md也非常适合使用版本控制系统进行版本管理。 总而言之,Python笔记md是一种简单、灵活且易于分享的笔记格式,可以有效提高编程学习和开发的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值