python接口测试自动化之python基础语法

一、pycharm的使用和python基本语法

(一)、pycharm的使用和python环境

1、python以及pycharm的安装

  • python 的版本选择:3.x 版本,不要安装2.x 版本,有很多语法不一样
  • 如何确定自己 python 版本: cmd: python
    • 不是内部命令:python没有正确安装,原因大概率是因为没有配置环境变量(配置环境变量后重启电脑生效)
    • 指定 python 的安装目录:一般来说是安装在 d:\python37
  • 测试python是否安装成功
    • cmd: python
    • cmd: pip ,或者 pip3 , 有任何一个出现命令不存在,
    • 额外注意:loadrunner 中也有pip,这个pip配置环境变量了之后,python中的pip也需要配置环境变量
  • prcharm 的版本选择:社区版够用
  • pycharm 只是一个工具,python 才是关键

2、pycharm 新建项目

  • 新建项目
    • file —> New Project
  • 退出项目
    • file —> Close Project
  • 切换项目
    • file —> Open
    • file —> Open Recent

3、文件、目录、包的创建和管理

  • Project —> 右键 ,可以新建文件、目录和包

4、pycharm 的基础使用

  • python 代码是保存到以 .py 结尾的文件当中
  • .py 文件又是放到各个文件夹(目录)下面的

5、如何运行代码:

  • 右键,点击 run
  • 命令行运行:点击底下的 Terminal
    • 进入项目路径
    • python 拼接好的路径/python文件.py

6、安装第三方库

  • 第三方库:是别人已经写好的 python 代码

  • 第一种方法:

    • 安装:pip install 库名
    • 卸载:pip uninstall 库名
  • 第二种方法:pycharm :不要勾选 user’s site package

  • 第三种方法:库放在国外的服务器上,需要用到国内安装源,python国内源

python国内源:
清华://pypi.tuna.tsinghua.edu.cn/simple
阿里云://mirrors.aliyun.com/pypi/simple/
中国科技大学 //pypi.mirrors.ustc.edu.cn/simple/
华中理工大学://pypi.hustunique.com/
山东理工大学://pypi.sdutlinux.org/
豆瓣://pypi.douban.com/simple/

(二)、python基本语法

1、基本语法

  • print 输出

    • 表示在屏幕上打印出(显示出)
    • 使用的任何的代码,双引号是半角,英文
    • print 默认输出是换行的,不同的数据之间用逗号隔开
  • python注释: 表示在 python 当中不会运行的文字(不会当成代码), 是说明下面的代码是什么?

    • # 表示单行注释 , Ctrl + /
    • “”” “”” 表示多行注释
    • ”’ ”’ 表示多行注释
  • 缩进:

    • 现在这个阶段,所有的代码全部顶格写,不要进行缩进。
  • 数值

    • 和数学中的数值表示是一样的(注意点:数值不用加引号)
  • 字符串

    • python 使用引号来表示字符串(一串文字)
  • 变量

    • 什么是变量:是用来存储数据
      • a = 100
      • b = 200
      • c = “ hello world”
    • 变量名的命名规范:
      • 只能包含数字、字母、下划线,
      • 不能以数字开头,
      • 不能有关键字( 注意点 )
        • python 中所有的关键字: keyword.kwlist
      • 尽量做到见名知意
        • 尽量不要用拼音
  • 标识符:(凡是我们自己取的名字,都是标识符。)

    • 规范:标识符由字母、数字、下划线组成,不能使用关键字
    • 标识符包括:变量名、函数名、类名、模块名、项目名
    • 在python中,所有标识符可以包括英文,数字以及下划线(_),但不能以数字开头。
    • python 中的标识符是区分大小写的,大写的 A 和小写的 a 不一样
  • 标识符的命名风格:

    • 下划线命名法:
      • 规范:单词字母小写,单词之间使用下划线连接
      • 如:max_number ,test_data
    • 大驼峰命名法:
      • 规范:每个单词的第一个字母大写
      • 如:MaxNumber , TestData
    • 小驼峰命名法:
      • 规范:第一个单词以小写字母开始,第二个单词的首字母大写
      • 如:maxNumber , testData

  • input 用户输入

    • 从控制台里面获取一个数据,获取到的类型是字符串类型

二、python中常见数据类型

(一)、数值类型 & 运算符

1、数值类型数据

  • 数值类型
    • 整数(int):整数
    • 浮点数(float):小数
    • 布尔值(bool):只有两个值 True 和 False

2、python 常见运算符

  • 算术运算符:

    • +
    • *
    • /
      • 除法运算一定要注意:除数不能为0
      • 除数如果为0,就会报错:ZeroDivisionError: division by zero
    • //
      • 整除
    • %
      • 余数:模运算

    # +
    print(5 + 6)
    # -
    print(7 - 8)
    # *
    print(2 * 3)
    # /
    # 只要是进行除法运算,得到的是一个 float
    print(4 / 3)
    print(4 / 2)
    
    # 除法运算一定要注意,除数不能为 0
    # 除数如果为0,就会报错:ZeroDivisionError: division by zero
    # 程序报错以后,就无法继续运行
    # print(2/0)
    # print('hello world')
    
    # // 得到的是一个整数。  整除
    print(4 // 3)
    
    # %  取余数 : 模运算
    print(4 % 3)
    
    # ** 幂运算 4的3次方
    print(4 ** 3)
    
  • 赋值运算符

    • =
    • +=
    • -=
    • *=
    • /=
    • //=
    • %=
    • **=
    name = 'yuze'
    age = 18
    
    #涨一岁
    age = age + 1
    print(age)
    
    #缩写 age += 1    ==>   age = age + 1
    age += 2
    print(age)
    
    age /= 3
    print(age)
    

  • 比较运算符: 比较运算得到的结果是一个 bool 值, True 或 False

    • <
    • >
    • <=
    • >=
    • !=
    > 大于
    print(5 > 4) # True
    
    < 小于
    print(6 < 3) # False
    
    >= 大于等于
    print(6 >= 3) # True
    
    <= 小于等于
    print(6 <= 3) # False
    
    != 不等于
    print(6 != 3) # True
    
    TODO: == 才是比较运算, 一个 = 是赋值运算
    print(6 == 6)
    

  • 逻辑运算 : 可以使用()提高优先级

    • and
    • or
    • not
    a = 3 > 4
    print(a)
    
    b = 4 != 5
    print(b)
    
    # 运算 and
    # 每一个都为 True
    
    print(a and b)  # False
    
    # 运算 or
    # 只要有一个为 True
    
    print(a or b)  # True
    
    # 练习
    
    a = True
    b = 5 == 4  # False
    c = 5 != 3  # True
    
    print(a and b or c)  # True
    print(a or b and c)  # True
    
    # python 的运算有没有优先级,如何设置优先级
    # 使用 () 设置优先级
    print(((a and b) or c) and b)
    
    # not 取反
    print(not(b))  # True
    
  • 身份运算

    • is
    • is not
  • 成员运算

    • in
    • not in
    # in
    
    name = 'yuz'
    
    print('u' in name)  # True
    print('uz' in name)  # True
    print('uai' in name)  # False
    
    # TODO: in 一定是连着的, yz 是一个整体
    print('yz' in name)  # False
    print('Y' in name)  # False
    

3、随机数模块: random (python 官方库)

  • 随机生成 0-1 之间的浮点数:random.random()

  • 随机生成 0-100 之间的浮点数:random.randint(1, 100)

    import random
    f_num = random.random()
    
    print(f_num)
    
    num = random.randint(0, 100)
    
    print(num)
    

(二)、字符串

本节问题:

问题一:python中如何表示字母,比如要将一个人的名字储存下来?

问题二:字符串如何定义?

问题三:字符串如果要换行怎么办?

问题四:数值类型的数据可以转换成字符串吗?

问题五:可以把两个字符串组成一个吗?

问题六;如何获取字符串中某个具体的字符?

1、字符串的定义:

  • 单引号、双引号:定义单行字符串

  • 三引号、三双引号: 多行字符串定义

  • 空字符串: s=”

  • str():

  • 注意点:字符串中有单引号时,外面用双引号注意区分

    """字符串的定义
    
    如何表示字符串:
    - 引号表示字符串
    - 单引号 ''
    - 双引号 ""
    - 三引号 ''' '''
    - 三双引号 """ """
    """
    
    name1 = "yuze"
    
    print(name1)
    
    name2 = 'yuze'
    
    print(name2)
    
    name3 = '''yuze'''
    
    print(name3)
    
    name4 = """yuze"""
    
    print(name4)
    
    print(name1 == name2 == name3 == name4)  # True
    
    print(name1 == name2)  # True
    
    print(name1 == name3)  # True
    
    print(name1 == name4)  # True
    

2、字符串的切片和下标取值

  • 1、下标索引取值

    • 下标取值:可以正向取,也可以反向取
    • 注意点:正向从 0 开始,反向从 -1 开始
    name = 'yuzwang'
    
    print(name[1]) # u
    
    print(name[0]) # y
    
    # 获取第3个字符
    
    print(name[2])  # z
    
    # 获取 g
    
    print(name[6])
    
    print(name[-1])
    

  • 2、切片: [:][::]

    • 问题:下标取值只能获取单个元素,现有字符串 str1=’hello python’ ,如果要获取出来 python 应该怎么做?
    • 切片的语法: 和下标取值一样使用中括号进行切片,有两种用法:
      • [a:b] :a代表起始位置下标, b 代表终止位置下标(左闭右开);
      • [a: b: c] : a代表起始位置下标, b 代表终止位置下标(左闭右开),c 代表步长。
    
    """字符串的切片 slice
    
      获取多个字符
    
      索引获取的公式:
    
          m_str[start:end:step]
    
      注意:end - start 的符号 必须和 step 的符号相同才可以获取到索引
    
      step 的值不能为0
    
    """
    
    name = 'yuzwang'
    
    # 要 1 和 2
    print(name[1:2]) # u
    print(name[0:1]) # y
    
    # TODO: 这个才是对的
    # TODO: 顾头不顾腚,取头不取尾,取左不取右
    print(name[0:2]) # yu
    print(name[3:6])  # wan
    
    # 什么是 step , 取完第一个索引,把索引 + 多少
    # step = 2
    print(name[3:6:2]) # wn
    print(name[1:5:3]) # ua
    
    # step 可以为负数
    print(name[5:1:-3]) # nz
    print(name[5:1:3])  # 取不到值 None
    print(name[1:4:-2])  # 取不到值 None
    
    # TODO: end - start 的符号 必须和 step 的符号相同才可以获取到索引
    # TODO:step 的值不能为0,否则会报错:ValueError: slice step cannot be zero
    print(name[1:5:0])
    
    # TODO: IndexError
    print(name[1000000]) # IndexError: string index out of range
    print(name[1:1000000])  # uzwang 不会报错,会取到所有值
    
    name = "yuzewang"
    
    # 省略 end ,表示取到最后
    print(name[1:])
    
    # 省略 start ,表示从 0 开始
    print(name[:5])
    
    # 复制,copy  从头到尾,
    # TODO: 面试题:复制字符串
    print(name[:])
    name_copy = name[:]
    print(name_copy)
    
    # 倒序  '123456' ==> '654321'
    # TODO:面试题:倒序一个字符串
    print(name[::-1]) # gnawezuy
    

3、字符串拼接和转义

  • + 号:’hello’ + ‘python’

  • 字符串转义:

    • \n: 换行符
    • \t: 水平制表符
    • 关闭转义:r’hello \n python’
    
    name = 'yuz'
    family_name = 'wang'
    
    print(name + family_name)
    
    print(name + ' ' + family_name)
    
    字符串和数字能不能相加
    
    print('yuz' + 7) # 字符串和数字不能直接相加,会报错:TypeError: must be str, not int
    
    print('yuz' + str(7))  # yuz7
    
    数据类型的转化
    
    print(int(name))  # 报错:ValueError: invalid literal for int() with base 10: 'yuz'
    
    print(int('12')) # 12
    
    print(bool(34)) # True
    
    bool 转化,只要是非0,非空的就是True
    
    字符串换行
    
    '\' 不会分开成两行
    
    name = "yuze ooasfjojo" \
    
                 "wefwllfjlj"
    
    print(name)  # yuze ooasfjojowefwllfjlj
    
    # 三引号换行,得到多行数据
    
    name = """yuze flaljlkfjlajl
    
    lsajllakj fjk
    
    sjljjfljladf
    
    aljfl
    
    """
    
    print(name)
    
    # 单引号中 \n 表示换行
    
    name = 'kaixina lajj\nlfljajljssfjdlk\njljajs'
    
    print(name)
    
    

4、字符串常用方法

  • join : 字符串拼接

name = "qin er cai"

# 字符串拼接

print(name + 'wang')

# 使用 join 拼接

print(name.join(['a','b','c']))  # aqin er caibqin er caic

# 时间 ['2020', '08', '03'] 用 / 连接起来

print('/'.join(['2020', '08', '03'])) # 2020/08/03

print('2020' + '/' + '08' + '/' + '03') # 2020/08/03


  • find : 查找元素的位置
# find:在字符串当中查找某个字符或者字符串的位置

# 会得到索引

  a = "wangyuze is coming"

  print(a.find('e')) # 7

  index = a.find('e')

  print(index) # 7

# 如果找的有两个呢?  i,会得到第一个

  print(a.find('i')) # 9

# 如果是一个子串呢? ng

  print(a.find('ng')) # 2

# 如果找不到怎么办?会得到 -1 ,这是规定

  print(a.find('isnot')) # -1

# 如果子串不在一起,也是找不到,返回 -1

  print(a.find('wn')) # -1

# index 约等于 find
# 区别:index 找不到元素的时候,会报错,find 找不到的时候返回-1

  print(a.index('ng')) # 2

  print(a.index('wn')) # ValueError: substring not found
  • count : 查找元素的个数
  # count 统计某个字符出现的次数
  m_str = 'foweofpweef'
  print(m_str.count('o')) # 2

  song = "我爱你,我喜欢你,我..."
  print(song.count('我'))  # 3

  • replace : 替换字符
  # replace 替换
  song = "我爱你,我喜欢你,我..."

  print(song.replace('你', 'ta'))  # 我爱ta,我喜欢ta,我...

  • split : 字符串分割

  # split  切分、切割   ==》 和 join 相反

  time_string = '2020/08/03'
  print(time_string.split('/'))  # ['2020', '08', '03']

  • format : 格式化输出

  • upper : 将字母大写


  # upper 所有字母都大写
  name = 'yuze'
  print(name.upper())  # YUZE

  • lower : 将字母小写

  # lower 所有字母都小写
  name = 'JECK'
  print(name.lower())  # jeck

  • strip : 去掉两边的特殊字符,如果什么都不传,就是去掉空格或者换行符

  # strip  去掉两边的特殊字符,如果什么都不传,就是去掉空格或者换行符
  name = '   yuze wang   '
  print(name.strip()) # yuze wang
  print(name)

  cp = "&雨泽&哈哈&"
  print(cp.strip('&')) # 雨泽&哈哈

  • len : 计算字符串长度

  # len 计算字符串的长度
  name = 'yuzewang '
  print(len(name)) # 9

5、字符串格式化输出

  • format 格式化输出

    • format() 功能强大,该函数把字符串当成一个模板,通过传入的参数进行格式化,并且使用 {} 作为特殊字符代替 %
    数据 格式 结果 描述
    5.11111 {:.2f} 5.11 保留小数点后两位
    0.25 {:.2%} 25.00% 百分比格式
    aa {:<10} aa 左对齐(宽度为10)
    aa {:^10} aa 中间对齐(宽度为10)
    • format 字符串的格式化
    ​```
    # 现在需要打印下面的格式:
    -------------------
    借条
    借款人:yuz
    债权人:double king
    金额:500
    -------------------
    
    loan_name = 'yuz'
    rich_man = 'double king'
    money = 500
    
    # # 方法一:
    # print("---------------------")
    # print('借条')
    # print('借款人:' + loan_name)
    # print('债权人:' + rich_man)
    # print('金额:' + str(money))
    # print('---------------------')
    # 
    # 
    
    # 方法二:
    # {} 表示占坑符,占位符
    # 位置一定要匹配,不能乱填顺序
    # print("""
    # -------------------
    # 借条
    # 借款人:{}
    # 债权人:{}
    # 金额:{:.2f} 万
    # -------------------
    # """.format(loan_name, rich_man, money))
    # 
    # 
    # # 方法三:
    # # f-string : python3.6 以后才支持
    # print(f"""
    # -------------------
    # 借条
    # 借款人:{loan_name}
    # 债权人:{rich_man}
    # 金额:{money} 万
    # -------------------
    # """)
    
    
  • 传统的格式化输出 %

    符号 描述
    %s 格式化字符串
    %d 格式化整数
    %f 格式化浮点数字,可指定小数点后的精度

(三)、列表和元组

1、列表

  • 列表的定义

    • 是一种数据类型,可以用来存储多个数据
    • 列表用 [ ] 来标识
    • 列表内部的元素可以是任意类型的
    • 列表是使用最频繁的数据类型之一
  • 列表的常见操作

    • 下标取值(索引取值):获取某一个元素

    • 切片操作:获取多个元素

      • 有步长的切片过程:先根据起始位置和终止位置,将内容切出来,然后再根据步长分为若干部分,然后将每部分的第一个元素拿出来,得出结果。
    • 修改元素的值:可以通过下标修改指定位置的元素。

      # 5 个人,5个大佬 , 使用列表
      big_boss = ['Demons', 'Go', 'EE', '上善若水', 'summer']
      print(big_boss)
      
      
      # 元素可以是任意的数据类型
      big_boss = ['Demons', 11, True, 33.33, 'summer']
      print(big_boss)
      
      big_boss = ['Demons', 11, True, 33.33, ['a','b','c']]
      print(big_boss)
      
      big_boss = ['Demons', 11, True, 33.33, ['a','b',['yuz',True]]]
      print(big_boss)
      
      
      # 索引: 获取索引为 0 的元素
      print(big_boss[0]) # Demons
      print(big_boss[-1]) # ['a', 'b', ['yuz', True]]
      print(big_boss[-2]) # 33.33
      print(big_boss[2]) # True
      
      # 获取 a
      print(big_boss[-1][0]) # a
      last_one = big_boss[-1]
      print(last_one[0]) # a
      
      # 获取 'yuz'
      print(big_boss[-1][-1][0]) # yuz
      
      
      # 切片
      print(big_boss[:3]) # ['Demons', 11, True]
      
  • 列表嵌套

    • 列表中如果有多层嵌套,取值时需要一层一层的取值

      lst = [
          'a',
          'b',
          [1,2,3]
      ]
      
      print(lst[0]) # a
      
      print(lst[-1][1]) # 2
      
      

  • 列表的方法

    • 增:append 、insert 、 extend
    • 删:pop 、 remove
    • 改:通过下标修改值
    • 查:index 、 count
    • 其他:reverse 、 sort
    方法 描述
    append 在列表的尾部加入一个元素
    insert 在指定位置插入一个元素
    extend 插入多个元素
    pop 删除一个元素(默认从列表尾部删除,也可以指定下标进行删除)
    remove 删除指定的元素(从前往后找)
    index 查找元素的位置,找到第一个就返回结果
    count 统计元素的个数
    sort 将列表的元素进行排序
    reverse 将列表内元素反序(头变为尾,尾变头)
    # TODO:坑
    dalaos = ['随风']
    
    new_dalao = dalaos.append('利己')
    print(dalaos) # ['随风', '利己']
    
    # append() 返回 None
    print(new_dalao) # None
    
    # 再添加多个,['一罐','本本','可爱','美雪'] 添加到最后
    dalaos.extend(['一罐','本本','可爱','美雪'])
    print(dalaos)
    
    
    # TODO: 坑2 报错:AttributeError: 'NoneType' object has no attribute 'append'
    new_dalao = dalaos.append('sfo').append('hello').append('sof')
    print(new_dalao)
    
    
    # 增加某个元素,修改的是原来的变量 lst
    lst = ['yuz', 'shanshan', 'rita']
    lst.append('裴纶')
    print(lst) # ['yuz', 'shanshan', 'rita', '裴纶']
    
    
    # insert 指定索引位置添加元素,不是获取索引,不用[]
    lst.insert(1, '仙人球')
    print(lst) # ['yuz', '仙人球', 'shanshan', 'rita', '裴纶']
    
    
    # extend 添加多个,可以合并 2 个列表
    lst.extend(['tiger', 'f2'])
    print(lst) # ['yuz', '仙人球', 'shanshan', 'rita', '裴纶', 'tiger', 'f2']
    
    
    lst = [1,2,3]
    lst.append(3)
    print(f"第一次尝试{lst}") # 第一次尝试[1, 2, 3, 3]
    # lst.extend(3)
    # print(f"第二次尝试{lst}") # 报错:TypeError: 'int' object is not iterable
    lst.extend([3])
    print(f"第三次尝试{lst}") # 第三次尝试[1, 2, 3, 3, 3]
    
    
    
    a = [1,2,3]
    b = [4,5,6]
    
    # b 是作为一个整体,一个元素,添加到 a 当中
    # a.append(b)
    # print(a) # [1, 2, 3, [4, 5, 6]]
    
    # b 是拆开里面元素,作为多个元素,添加到 a 当中
    a.extend(b)
    print(a) # [1, 2, 3, 4, 5, 6]
    
    """列表的删除
    - remove
    - delete
    - pop
    
    """
    
    # remove: 在列表当中删除指定的值
    big_boss = ['糖', '木易', '均价']
    big_boss.remove('木易')
    print(big_boss) # ['糖', '均价']
    
    
    # delete 异类:尽量不要用
    # del big_boss[0]
    # print(big_boss) # ['均价']
    
    
    # pop  0 代表索引为 0
    big_boss.pop(0)
    print(big_boss) # ['均价']
    
    # 获取索引为 0 的值
    print(big_boss[0])
    
    
    big_boss.append('木易')
    print(big_boss) # ['均价', '木易']
    
    """列表的修改
    
    lst[0] = 1
    """
    
    lst = [1,2,3]
    
    lst[1] = 'a'
    print(lst) # [1, 'a', 3]
    
    
    lst[1],lst[2] = 'c', 'd'
    print(lst) # [1, 'c', 'd']
    
    
    lst[1:] = 5,6
    print(lst) # [1, 5, 6]
    
    """列表的方法
    - index
    - count
    - sort
    - reverse
    - clear
    
    """
    
    lst = [4,5,6,5]
    
    # # 统计
    # print(lst.count(5)) # 2
    #
    # # index 查找得到第一次出现的索引值
    # print(lst.index(5)) # 1
    #
    # # sort 排序
    # print(lst.sort()) # None
    #
    # lst.sort()
    # print(lst) # [4, 5, 5, 6]
    #
    #
    # # reverse 反向,倒序 ,  相当于 [::-1]
    # lst.reverse()
    # print(lst) # [6, 5, 5, 4]
    
    
    # 反向排序
    lst.sort(reverse=True)
    print(lst) # [6, 5, 5, 4]
    
    
    # clera 清除一个列表
    lst.clear()
    print(lst) # []
    

2、元组

  • 元组的定义:

    • 元组定义在小括号中,元组内部的数据:它支持数字,字符串甚至可以包含元组(即嵌套)
  • 元组的常见操作

    • 下标取值:元组内部的数据是有序的,可以通过下标获取对应的元素
  • 注意点

    • t = () 空元组
    • t = (1,) 只有一个数据的时候要注意加逗号
    • 元组的值不可以修改,是属于不可变数据
  • 元组的方法

    • count : 查找元素的个数
    • index :查找元素下标
    tuple_yuz = ('yuz','一罐',['闲人','七七','小骄傲'])
    # 修改的是元组的元素,元组的元素是列表
    # tuple_yuz[2] = ['新列表']
    # print(tuple_yuz) # 不能修改元组的元素
    
    # 为什么这里可以改??
    # 元组的不可变是相对的,不是说里面所有的内容都完全不能变
    # 只要看索引的前面是不是一个可变的类型
    tuple_yuz[2][0] = ['新列表']
    print(tuple_yuz)
    
    
    tuple_yuz = ('yuz','一罐',{'tuple':'yuze'})
    # 索引前面是元组,代表我们要修改的是元组的元素,不可以
    # tuple_yuz[2] = 'hello world'
    
    # tuple_yuz[2] 是字典,可变类型,可以直接修改
    tuple_yuz[2]['name'] = 'hello world'
    print(tuple_yuz)
    
    
    # 索引前yuz是列表,可以改变
    yuz = ['yuz','一罐',('四叶草','晓峰')]
    yuz[2] = 'hello'
    print(yuz)
    
    # yuz[2]是元组,不可变
    yuz[2][1] = 'youxi'
    
    tuple_demo = ()
    print(tuple_demo)
    
    
    # TODO:坑 ,一个元素的元组表示,不是一个元组,而是去掉括号后的原始数据类型
    # tuple_demo_2 = (1)
    # print(tuple_demo_2)
    
    # 如果想表示一个元素的元组,记得务必在元素后面加一个逗号
    # tuple_demo_3 = (1,)
    # print(len(tuple_demo_3))
    
    tuple_demo_4 = (1,3,4,5,5,)
    print(len(tuple_demo_4))
    tuple_demo_5 = 1
    print(tuple_demo_5)
    
    
    # 元组解包
    family_name,name = ('wang','yuze')
    # family_name,name = ('wang','yuze','hello') # 值要一一对应,否则会报错
    print(family_name)
    print(name)
    
    a,b = 3,4
    print(a)
    print(b)
    
    
    family_name,name,*other = ('wang','yuze','hello','world')
    print(family_name)
    print(name)
    print(*other)
    

3、字符串、列表、元组总结

  • 序列类型:
    • 字符串、列表、元组,统称为序列类型数据(内部的元素是有顺序的)
  • 通用操作:
    • 下标取值:
    • 切片:
    • 获取元素总数: len()

(四)、字典和集合

  • 问题:
    • 使用一个列表存储了一个学生信息,姓名,年龄,电话号码,stu = [‘小明’, ’18’, ‘13812341234’]
    • 问题一:当前如果电话号码写错了,怎么修改
    • 问题二:当前列表中有10个设置100个元素,不知道电话号码具体的下标,怎么修改电话号码

1、字典

  • 字典的定义:

    • 也是用来存储多个数据的

    • 字典:字典用 {} 来标识

    • 字典能够表示元素更具体的意思,每个元素表示的意义是什么,可以通过 key 命名

    • 字典的结构:就是将它看做是一个 {key:value} 键:值 对的集合,键必须是唯一的(在一个字典中)

    • 空字典 : {}

    • 字典定义的方式:

      # 方式一:
      dic = {'name':'musen', 'age':18}
      
      # 方式二:
      dic = {name = 'musen', age = 18}
      
  • 注意点:

    • 字典中的键必须是唯一的
    • key 不能出现重名,在一个字典当中,key 之间是不一样的
    • key 不能变的,列表是不能作为 key 的
    • 可变类型数据:字典定义后可以修改内部元素
    • 注意点:字典的键必须是不可变类型的(一般情况下都是字符串),值可以是任意类型的数据(字典,元组,列表等等都可以)
  • 字典的增删改查

      • 通过指定键去添加相应的值
        dic[key] = value

      • update() : 将一个字典的所有元素更新到另一个字典中

      # 简单理解
      dic.update({'a':1, 'b':2})
      
      
    • 改:通过指定键去修改对应的值
      dic[key] = value

      • pop() : 删除指定的键,删除的键不存在会报错(避免错误可以添加默认值)
        dic.pop(key)

      • popitem() : 删除一个键值对,删除最后一个添加的元素

        • 之前版本是随机删除一个元素,python3.7新特性,删除最后添加的元素
      • 关键字 del : 通过键删除

        del dic[key]

    • get() : 获取键对应的值
    • keys() : 获取所有的键,可以用 list 将结果转换成列表
    • values() : 获取所有的值,可以用 list 将结果转换成列表
    • items() : 获取所有的键值对,可以用 list 将结果转换成列表,列表中每个键值对组成一个元组。
    # 列表:当每个元素有具体的意义,你又想去单独获取的时候,可读性不强
    beisheng = ['星际穿越', '蜘蛛侠', '上海堡垒', '分手大师', '前任3']
    print(beisheng[2])
    
    
    # 字典:key: 元素的名称, value: 元素的值 ,  键值对:成对
    # 用 {} 在最外面
    # key: value, key1: value1
    beisheng = {'favor':'星际穿越','hate':'蜘蛛侠','first':'上海堡垒','last':'分手大师','twice':'前任3'}
    
    print(beisheng['hate']) # 蜘蛛侠
    
    
    # 重名的key
    beisheng = {'favor':'星际穿越',
                'hate':'蜘蛛侠',
                'first':'上海堡垒',
                'favor':'分手大师',
                'twice':'前任3'}
    # favor 后面的值会覆盖前面的值
    print(beisheng['favor']) # 分手大师
    
    print(beisheng) # {'favor': '分手大师', 'hate': '蜘蛛侠', 'first': '上海堡垒', 'twice': '前任3'}
    
    
    # key 不能是列表
    # beisheng = {'favor':'星际穿越',
    #             ['hate']:'蜘蛛侠',
    #             'first':'上海堡垒',
    #             'favor':'分手大师',
    #             'twice':'前任3'}
    # print(beisheng) # 报错:TypeError: unhashable type: 'list'
    
    
    # 键为数字: 没有意义,不建议使用
    beisheng = {1:'星际穿越',
                3:'蜘蛛侠',
                2:'上海堡垒',
                5:'分手大师',
                4:'前任3'}
    print(beisheng) # {1: '星际穿越', 3: '蜘蛛侠', 2: '上海堡垒', 5: '分手大师', 4: '前任3'}
    
    beisheng = {'favor':'星际穿越',
                'hate':'蜘蛛侠',
                'first':'上海堡垒',
                'last':'分手大师',
                'twice':'前任3'}
    
    # 获取,查
    print(beisheng['hate'])
    # 字典没有索引和切片
    
    
    # 修改
    beisheng['hate'] = '蝙蝠侠'
    print(beisheng) # {'favor': '星际穿越', 'hate': '蝙蝠侠', 'first': '上海堡垒', 'last': '分手大师', 'twice': '前任3'}
    
    
    # 添加, 和修改是一样的
    # 什么时候是修改,什么时候又是添加?
    # 看 key:当 key 已经存在的时候,是修改,当之前没有这个key,就是添加。
    beisheng['scared'] = '贞子'
    print(beisheng)
    
    beisheng['scared'] = '午夜凶铃'
    print(beisheng)
    

2、集合

  • 定义:

    • 集合中的元素不能重复
    • 花括号 或 set() 函数可以用来创建集合
  • 注意:

    • 要创建一个空集合你只能用 set() 而不能用 {} ,因为后者是创建一个空字典
  • 集合的方法:

    • 增加元素 : add
    • 删除元素 :pop , remove
    • 自动化测试中很少用集合来存放数据,更多内容请自行扩展
  • 集合的重要应用场景:去重

  • 集合的交集、并集、差集

    • a & b : 集合 a 和 b 中都包含了的元素
    • a | b : 集合 a 或 b 中包含的所有元素
    • a – b : 集合 a 中包含而集合 b 中不包含的元素
    # 集合不是键值对
    # 集合是无序的
    # 不能通过索引获取
    # 重复的元素直接丢掉,集合目前我们使用的最多的功能就是去重
    set_yuz = {'yuz','鲁西西','闲人','yiguan'}
    print(set_yuz)
    # print(set_yuz[1]) # 会报错
    print(len(set_yuz))
    
    # 去重
    set_yuz = list(set(['yuz','鲁西西','闲人','yuz']))
    print(set_yuz)
    
    
    # split 分割
    # a = 'hello world'
    # b = a.split('w')
    # print(b)
    
    a = 'hello/world/sofo/sooof'
    b = a.split('/',1) # 数字1代表分割一次
    print(a) # a 是字符串,不会变
    print(b)
    

(五)、数据类型相互转换

1、字符串的转化

  • 字符串转换成列表

    • 字符串转换成list 的时候,str可以作为迭代对象,直接放入;也可以使用split对字符串进行切割。然后返回list
    s = '1ab1cd'
    print(list(s))  # ['1', 'a', 'b', '1', 'c', 'd']
    print(s.split('1')) # ['', 'ab', 'cd']
    

  • 字符串转换成元组

    s = '1ab1cd'
    print(tuple(s)) # ('1', 'a', 'b', '1', 'c', 'd')
    

  • 字符串转换成字典

    a='1ab1cd'
    b='123456'
    print(zip(a,b)) # <zip object at 0x00000000022952C8>
    print(dict(zip(a,b))) # {'1': '4', 'a': '2', 'b': '3', 'c': '5', 'd': '6'}
    
    
    a='1ab1cdd4e5'
    b='123456'
    print(zip(a,b)) # <zip object at 0x00000000022952C8>
    print(dict(zip(a,b))) # {'1': '4', 'a': '2', 'b': '3', 'c': '5', 'd': '6'}
    

  • 字符串转换成集合

    a='1ab1cd1d'
    print(set(a)) # {'1', 'a', 'c', 'b', 'd'}
    

2、列表的转化

  • 列表转换成字符串

    • 列表里如果有int类型,字典,元祖,列表,则join方法不可用
    list = ["3","d","aaa"]
    print("".join(list)) # 3daaa
    print(" ".join(list)) # 3 d aaa
    print("!".join(list)) # 3!d!aaa
    

  • 列表转换成元组

    list = ['1','2','3','a',(1,2,3),1,[1,2],{"a":1}]
    print(tuple(list)) # ('1', '2', '3', 'a', (1, 2, 3), 1, [1, 2], {'a': 1})
    

  • 列表转换成字典

    list1 = ['1','2','3','4','a',(1,2,3),5,6]
    list2 = ['a','b','c','d','e','f',[1,2],{"g":"h"}]
    dict1 = dict(zip(list1,list2))
    print(dict1)
    # {'1': 'a', '2': 'b', '3': 'c', '4': 'd', 'a': 'e', (1, 2, 3): 'f', 5: [1, 2], 6: {'g': 'h'}}
    

  • 列表转换成集合

    list = ['1','2','3','3']
    print(set(list)) #{'3', '1', '2'}
    

3、元组的转化

  • 元组转换成字符串

    • 元组里如果有int类型,字典,元祖,列表,则join方法不可用
    tuple = ('1','2','3','4','2','a')
    print(''.join(tuple)) # 12342a
    
  • 元组转换成列表

    tuple = (1,2,3,4,5,'2','a')
    print(list(tuple)) # [1, 2, 3, 4, 5, '2', 'a']
    
  • 元组转换成字典

    tuple1 = ('1', '2', '3', '4',111,(11,22,33),"")
    tuple2 = ('a', 'b', 'c', 'd','e','f','h','g','i','j','k')
    dict1 = dict(zip(tuple1, tuple2))
    print(dict1) # {'1': 'a', '2': 'b', '3': 'c', '4': 'd', 111: 'e', (11, 22, 33): 'f', '': 'h'}
    
  • 元组转换成集合

    tuple1 = ('1','2','3','4',4,'4',4,1)
    print(set(tuple1)) # {1, 4, '3', '1', '2', '4'}
    

4、字典的转化

  • 字典转换成字符串

    • 对于生成字符串,需要先生成list和tuple,然后再由list和tuple生成str
    dict1 = {1:'a',2:'b',3:'c'}
    
    list1 = list(dict1.values())
    print("".join(list1)) # abc
    
    tuple1 = tuple(dict1.values())
    print("".join(tuple1)) # abc
    
  • 字典转换成列表/元组/集合

    • 字典可以使用 dict.keys() 和 dict.values() 返回迭代器,通过list和tuple直接生成列表和元祖
    dict1 = {1:'a',2:'b',3:'c'}
    print(list(dict1.keys())) # [1, 2, 3]
    print(list(dict1.values())) # ['a', 'b', 'c']
    
    print(tuple(dict1.keys())) # (1, 2, 3)
    print(tuple(dict1.values())) # ('a', 'b', 'c')
    
    print(set(dict1.keys())) # {1, 2, 3}
    print(set(dict1.values())) # {'a', 'b', 'c'}
    
    print(tuple(dict1.items()))  #生成元祖为单位的元祖
    # ((1, 'a'), (2, 'b'), (3, 'c'))
    print(list(dict1.items()))  #生成元祖为单位的列表
    # [(1, 'a'), (2, 'b'), (3, 'c')]
    print(set(dict1.items()))   #生成元祖为单位的集合
    # {(2, 'b'), (3, 'c'), (1, 'a')}
    

5、集合的转化

  • 集合转换成字符串

    • 集合是无序的,每次转换成的字符串值都不一定一样,也可以先转为列表或者元祖,再转换成字符串
    set1 = {"1","2","ac"}
    print("".join(set1)) # 2ac1
    print(type("".join(set1))) # <class 'str'>
    
  • 集合转换成列表/元组

    set1 = {1,2,3,4,5,6}
    print(list(set1)) # [1, 2, 3, 4, 5, 6]
    print(tuple(set1)) # (1, 2, 3, 4, 5, 6)
    
  • 集合转换成字典

    • 无意义的映射,不推荐
    set1 = {1,2,3,4,5,6}
    set2 = {'a','b','c','d'}
    print(dict(zip(set1,set2)))
    # {1: 'd', 2: 'a', 3: 'b', 4: 'c'}
    

三、控制流程

(一)、条件语句

  • if条件判断

    • 分支结构,常用的表现方式:
      • if(条件表达式):……
      • if(条件表达式):……else:……
      • if(条件表达式):……elif(条件表达式):……elif(条件表达式):……else:
# if的写法(else可以省略)
if (条件表达式):
		pass
else:
		pass

  
if (条件表达式):
		pass
elif (条件表达式):
		pass
else:
		pass


# 例如:
username = "yuze"
if username == "yuze" or username == "yuzewang":
		#缩进表示条件满足以后需要执行的子代码,是一个分支
		print("登录成功")
elif username == ""
		print("请输入用户名")
elif username == "Demo"
		print("没有该用户")
else
		print("登录失败")
  • if语句用于验证某个条件

    • 当条件为真时,运行if下面的代码块,否则运行else下面的代码块
    • 条件当中,只要执行了一个分支,其它分支就不会继续执行了
      • 条件表达式:要得到的值是一个bool类型,True, False
  • 使用if需要注意的点

    • 所有分支流必须以if开头
    • 语句中的else可以省略
    • if与elif后面必须加条件表达式,else后面不能加条件表达式
    • 一个判断分支下只有一个if,一个else,可以有多个elif
    • 分支下按顺序执行代码,只要执行了一个分支下的代码,其他的分支则都不会执行

(二)、程序debug调试

  • 是暂停代码的运行去获取现在的数据状态
    • print
    • pycharm中的debug
      • 先打断点
      • 再执行debug
      • 下一步按钮
      • 查看数据
  • 打断点,是告诉程序我应该在哪里暂停

(三)、while循环

  • 循环控制流

    • 循环语句,用于验证某个条件
    • 当条件为真时,运行循环下的代码块,否则结束循环
    • 分类:
      • while 循环
      • for 循环
  • while循环作用:用来重复执行某个操作

  • while 语法

while 判断条件:
		执行代码

# 例如:

times = 0
while times < 999:
		print("我说了{times}次")
		times = times + 1

      
continue: 表示手工进入下一个循环体,进入下次循环


break:表示手工强制退出整个while循环


(四)、for循环

  • 作用:

    • 用来遍历对象
    • 从对象的第一个元素到最后一个元素,依次访问
    • for循环会自动+1
  • 语法

    • for 元素 in 数据集合:执行代码
    • 数据集合可以是:列表,元组,字典,字符串,也可以是指定的数据范围
    • for循环嵌套,子循环执行完,才会回到母循环执行
for 迭代变量 in 字符串|列表|元组|字典|集合:
   	代码块

# 例如:

add = "//c.biancheng.net/python/"
#for循环,遍历 add 字符串
for ch in add:
   	print(ch,end="")   
   
   
continue:手工进入下一个循环体,进入下次循环    

break:手工强制退出整个while循环
  • break

    • 常用在循环结构中
    • 在循环中遇到break,就跳出循环
  • continue

  • 常用在循环结构中

  • 在循环中遇到continue,就跳出本次循环,继续下一次循环

(五)总结知识点

  • for经常用到的场景:如果有一个现成的列表,字符串,字典,就用for
  • while经常用到的场景:不知道什么时候结束循环
  • 同时获取列表的索引和值
for i,value in enumerate(list):
		print(i, value)
  • 同时获取字典的键和值(常用)
for k,v in mdict.items():
		print(k, v)
  • 获取所有的value
for value in mdict.values():
		print(value)
  • 获取所有的key
for key in mdict.keys():
		print(key)
		  	
for k in mdict:
		print(k)
  • range() 函数

    • 表示循环某一个数据段
    • range(start,end,step),与切片类似,包前不包后
    • 打印100遍
    for i in range(100):
    		print(i)
    

四、函数和函数参数

(一)、函数定义和调用

1、函数的定义

  • 函数的概念:以数学函数来理解

  • 作用:传入一个自变量,会得到一个另外的变量,这个变量会根据自变量变化而变化

  • 用于存储一段代码。 是封装

  • 定义函数关键字:def

  • 为什么要写函数:方便好用、复用性高

  • 函数名:属于标识符,遵循标识符的命名规则:

    • 函数的名称是一个标识符:数字、字母、下划线,不能是内置关键字
    • 函数名遵循蛇形命名:下划线命名
    • 函数名称要见名知义
    • 函数命名的重要性:函数的名称会告诉读代码的人:这个函数的作用是什么
  • 语法:

    def 函数名(参数):
    		函数内部功能代码一
        函数内部功能代码二
        函数内部功能代码三
        函数内部功能代码四
        
        
    def add(a,b):
    		print(a+b)	
    
    
  • 函数中的代码如何运行?

    • 函数定义时,函数的代码不会被执行,只有当函数被调用时,函数中的代码才会被执行
  • 不要在一个文件中定义两个同名函数,后面的会覆盖前面的

def add (a,b):
		print(a+b)
def add (a,b):
		print(a-b)
		
add(1,2)  # -1

2、函数的调用

  • 使用函数的过程叫做调用函数;调用的时候会给变量赋值,即变量 = 值

  • 调用方法:

    函数名()

  • 函数的相互调用

    • 在函数中调用另外一个函数
    • 函数调用是去执行函数体内部逻辑
    • 避免两个函数相互调用
    • 不要调用自己

(二)、函数的返回值

  • return 的作用:
    • 返回值数目 = 0;返回 None
    • 返回值数目 = 1:返回object
    • 返回值数目 > 1:返回tuple
  • 疑问:为什么要用return?什么时候用return?
    • 根据需求,当需要返回的时候就返回,不需要返回的时候就不返回。
  • 注意点:
    • 1、return 是用来给函数返回结果的。
    • 2、当函数执行到return 时函数执行结束。
    • 3、函数没有定义return,默认的返回值为None
  • 现在有两件事,写成两个函数

(三)、函数参数

  • 1、参数的定义

    • 函数名后面的括号汇总定义参数
  • 2、形参与实参

    • 在函数定义的时候出现,是变量名,是自己定义的
    • 调用时实际传递的参数为:实参,是函数调用时出现的,实际参数是将要赋给变量名(形参)的值
    • 实参和形参要配对,成对出现的,下面情况都是不行的
      • 只有实参,没有形参
      • 只有形参,没有实参
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(1,2)  # a,b是形参, 1,2 是实参 
    
  • 位置参数

    • 函数的形参和实参是成对出现的,一一对应的
    • 函数调用的时候一定要检查好参数的个数
    • 位置参数概念
      • 形参和实参的这种位置关系叫位置参数
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(1,2)  # 1对应a, 2对应b
    
  • 关键字参数

    • 关键字参数,函数调用的时候,给实际参数贴标记,标记是形参的变量名
    • 通过关键字参数,可以不按顺序配对
    • 关键字参数要放在位置参数的后面
    • 关键字参数的作用:当参数很多时,可以使用
    def add (a,b):
    	print(a+b)
    	return(a+b)
    add(b=3,a=2)
    
  • 默认参数

    • 在函数定义的时候,给形式参数一个默认的值
    • 调用函数的时候,可以不用赋值给默认参数
    • 使用默认参数:可以少些实际参数
    • 放在位置参数后面
    def add (a,b=8):
    	print(a+b)
    	return(a+b)
    
  • 不定长参数

    • 不定长参数表示方式: * **
    • * 当在一个形参前加*,他会收集所有剩下没有配对的实际参数(位置参数),把剩下的数据组成一个元组
    • *args 存放很多位置参数
    def add (a,*b):
    	print(a)
    	print(b) 
    add(1,2,3,4)   # 1,(2,3,4)
    
    def add (a,*b):
    	print(a)
    	print(b)
    add(1,2,3,4,c=1) #报错:默认参数要放到位置参数后面,不定长参数放到位置参数后面
    
  • **只能收集关键字参数

  • **kwargs 存放很多关键字参数

  • 将数据转换为字典的形式

def add (a,**b):
  	print(a)
  	print(b)

add(1,c=1,d=2)  # 1  {'c': 1, 'd': 2}
  • 不定长参数的作用

    • 在参数定义的时候,不知道有多少个实际参数(关键字参数)
  • 拆包:

    • 列表、元组拆包
      • 会拆成位置参数
      • 函数定义当中args 表示不定长的位置参数,在调用的时候,叫做拆包、解包
      • 调用的时候,把 一个列表或元素变量传入函数,在前面加,就可以比那成多个值
    def marry(male,female):
    		print(male)
    		print(female)
    
    couple = ("老王","小星星")
    
    marry(*couple)
    
    
    • 字典拆包
      • 会拆成关键字参数
    couple = {"male":"小王","female":"老刘"}
    
    marry(**couple)
    
    

(四)、函数作用域

  • 是局部作用域
    • 在定义函数时,设置的变量为局部变量
    • 局部变量不能在全局作用域获取
    • 函数内部局部作用域可以用全局变量
    • 在函数外部不能修改函数内部的变量
    • 在函数内部可以修改全局变量,不过需要用global声明是全局变量 例如:global c

(五)、内置函数

  • print :输出

  • input :输入

  • type :查看数据类型

  • range :生成数据

  • id :获取数据内存地址

  • int、float、str、bool、list、dict、tuple、set :代表对应的数据类型,转换数据类型

  • max :获取最大的值,可以传多个参数,可以传列表

  • min :获取最小的值,可以传多个参数,可以传列表

  • sum :求和

  • enumetate:

    # enumerate() 将列表中的元素及其位置转换为成对的元组
    m_list = ['aa', 'bb', 'cc', 'dd']
    print(list(enumerate(m_list)))
    # [(0, 'aa'), (1, 'bb'), (2, 'cc'), (3, 'dd')]
    
    print(list(enumerate(m_list, start = 1)))
    # [(1, 'aa'), (2, 'bb'), (3, 'cc'), (4, 'dd')]
    
  • eval :可以去掉一个字符串的引号

    m_str = "6>7"
    print(m_str)
    print(eval(m_str))   # False
    m_str = '{"username":"yuz","age":18}'
    print(m_str)          # {"username":"yuz","age":18}
    print(type(m_str))    # <class 'str'>
    print(eval(m_str))    # {'username': 'yuz', 'age': 18}
    print(type(eval(m_str))) # <class 'dict'>
    
  • filter :过滤某些数据 filter(调用函数,列表)

li = [2,3,4,5,6,7]
def get_odd(value):
    if value % 2 == 0:
        return True
    return False
    
res = filter(get_odd, li)
print(list(res)) # [2, 4, 6]
  • map :
li = [2,3,4,5,6,7]

def square(value):
    return value ** 2

res = map(square, li)
print(list(res))  # [4, 9, 16, 25, 36, 49]
  • zip :
li_1 = ["yuz","hello","world"]
li_2 = [43,12,15]

print(list(zip(li1,li2)))  # [('yuz', 43), ('hello', 12), ('world', 15)]

a = zip(li1, li2)
print(dict(a))  # {'yuz': 43, 'hello': 12, 'world': 15}

(六)、模块和包

  • 模块

    • 模块,就是一个带 .py 后缀的python 文件,一个模块里面会有很多的函数,类
    • 模块名称:是一个标识符,符号标识符命名规则
      • 数字、字母、下划线,不能以数字开头,不能是关键字
      • 模块名称命名一般是使用下划线的形式命名,驼峰, d1_review.py
      • 模块名称不能和 python 内置的模块名称重合
    • 模块作用:
      • 有逻辑的组织python代码
      • 把相关功能的代码写到一个模块里能让代码更好用,更易懂
    • 包,package,就是一个python文件的文件夹,里面会有一个或多个模块
    • 包含一个_init_.py 模块的文件夹,这个模块可以什么都不定义,可以只是一个空文件夹
    • 标准库,第三方库,实现特定功能的代码集合,一个模块,也可以是一个包
    • python3 新版本,不带_init_.py 同样可以作为包使用
  • 模块导入

    • 是模块间变量和函数的互相使用 ,需要使用 import 的关键字

    • import … 后面只能跟 模块,不能跟函数,变量

    • from .. import … 后面可以跟模块,函数,类,变量

    • 导入自己的模块,别人的第三方模块,一般使用from import ,不用import..

      • google内部约定,导入模块只导入模块这一层,然后使用 模块名.函数名() 来调用函数

        from class_9_file import demo01
        
        demo01.test01_fun()
        
      • import .. 调用函数的时候需要些很长的前缀,比较麻烦

    • 不建议使用:from… import *

      • 导入模块或者包里面,所有的类、函数、变量
      • 导入所有,如果重命没有解决方法
    • as 重命名 – 避免同名函数冲突

      • 导入时导入到模块这一层,使用时使用模块名.函数名

      • 使用别名

        • 别名就是重命名,就是原函数名很长,为了方便使用函数
        from class_9_file import demo01 as d
        
        d.test01_fun()
        
    • 不要用相对导入,要绝对导入,就是从根目录开始导入

五、文件及路径

(一)、文件

1、打开文件和关闭文件

  • 打开文件,使用内置函数 open()

    • open(” path/文件名.后缀 “)
  • 特别注意:打开文件不管进行什么操作后,一定要关闭文件,否则会出现数据不对,或者写入内容不生效,文件无法再次被打开等情况

    f = open("python32.txt")
    f.close()
    
  • 为了避免忘记关闭文件,可以使用with语句,操作完成后会自动关闭文件

    with open('python32.txt','r',encoding='utf8') as f:
        print(f.read())
        
    with open('python32.txt','a',encoding='utf8') as f:
        print(f.write())
    
  • 不在同一路径下要用绝对路径,windows要加 r 防止转义,有反斜杠,mac不用加

    with open(r'J:\学习资料\Study\PythonAndSelenium\柠檬班python自动化课程\python32_API\class_09_file\python32.txt') as f:
      print(f.readline())
    

2、读取文件

  • mode 打开方式

    • r 以只读方式打开文件(默认),一般用于文本文件,如:txt。文件指针默认放在文件开头
    • b 以二进制格式打开文件。一般用于非文本文件,如:图片、视频
    • rb 以二进制的形式打开并读取
  • read() 读取

    with open("python32.txt", mode = 'r', encoding = 'utf8') as f:
        print(f.read())
        
        
    with open('1.png', mode= 'rb') as f:
        print(f.read())
    
  • readline() 读取一行

    with open('python32.txt', encoding = 'utf8') as f:
        print(f.readline())
    

  • readlines() 读取所有行,会以列表的形式展示

    with open('log.txt', encoding = 'utf8') as f:
        print(f.readlines()) # 可以显示换行符
    

3、写入文件

  • mode 写入方式

    • w 新建写入
      • w比较危险,如果之前已经有同名的文件,用w会覆盖之前的内容,w只能用于新建写入
    • a 追加写入
      • 如果文件名不存在,是先新建再写入;如果文件名存在,则为追加
    • wb 以二进制打开一个文件用于只写
      • 如果文件名存在,则覆盖,不存在,则新建写入
    • ab 以二进制打开一个文件用于追加
      • 如果文件存在,文件指针会放在文件结尾处
    with open('python32.txt', mode = 'w', encoding = 'utf8') as f:
        f.write('裴纶')
        
    with open('python32.txt', mode = 'a', encoding = 'utf8') as f:
        f.write('哈哈哈')
    
    • + 表示可以同时读写某个文件
      • r+ 可读,可写
      • w+ 可读,可写
      • a+ 可读,可写

(二)、路径

1、路径

  • sys . path 包含项目开始根目录路径和 python 内置的目录路径

    • 模块导入的搜索路径: sys.path
      • 模块导入不了时可以用来检查
      • python去查找包或模块,相当于python里的地图
      • 返回的是一个列表
  • os 是 python 内置的模块需要用 import 导入: import os

  • 找模块

    • 项目开始根目录
    • python内置目录
    • 不建议将写的模块存放在python的安装目录下
    • python目录主要是放外部的库或第三方的模块

2、路径处理

  • python中一般不直接写入绝对路径, 而是通过代码获取

  • 获取当前文件的路径:

    abs_path = os.path.abspath(_file_)

    _file_ 表示运行的文件的名称

  • 获取当前文件的目录路径: 两种写法,用第一种绝对路径

    dir_name = os.path.dirname(abs_name)

    dir_name = os.path.dirname(_file_)

  • 获取不与当前文件同一个目录下的文件路径

    • 1 .先获取当前文件的绝对路径
    • 2 .获取当前文件的目录路径
    • 3 .当前文件的目录路径和该文件拼接
    比如,获取pac01 下面的 demo.txt:
    txt_file_path = os.path.join(dirname, 'pac01', 'demo.txt')
    
    读取图片文件(二进制格式)
    dir_name = os.path.dirname(os.path.abspath(file))
    png_pic = os.path.join(dir_name,'1.png')
    f = open(png_pic,mode='rb')
    print(f.read())
    f.close()
    
    

3、路径操作

  • os.path.abspath() 获取绝对路径

  • os.path.dirname() 获取文件/目录所在路径

  • os.path.join(a, b) 连接两个部分的路径,组成一个完整路径

  • os.getcwd() 获取当前工作路径

  • os.chdir() 切换工作路径

  • os.mkdir() 在某个目录下创建一个新目录

  • os.rmdir() 删除一个目录

  • os.listdir() 获取当前路径下的目录,返回列表格式数据

  • os.path.isdir() 判断当前文件是否是目录,返回布尔值

  • os.path.isfile() 判断当前文件是否是文件,返回布尔值

六、异常

(一)、异常处理

  • 异常
    • 当程序运行中检测到一个错误时,无法继续执行,出现一些错误提示,这就是异常。
    • 程序遇到异常不会再执行,我们要改变程序碰到异常的行为

(二)、异常类型的捕获

  • 语法一:try…except….

    • 程序先执行try中的代码,一旦try中某个代码报错, 会直接跳到except,try剩下的代码不会执行

      try:
        	 要执行的可能发生异常的代码
      except:
        	 程序发生异常后,你希望程序做的事情
      
      try:
      		1/0
      except IndexError as e: 
      		print(e)
      # 其中as e可以在后面用来展示异常信息,但不能展示异常类型
      
  • 语法二:try…except….finally

    try:
    		1/0
    except ZeroDivisionError as e:
    		print("不能除以0")		
    finally:
    		print("无论异常与否,都会继续执行的代码")	
    
    # 运行结果:
    # 不能除以0
    # 无论异常与否,都会继续执行的代码
    
  • try…except…else

try:
	1 / 0
	print("正常执行的代码")
except ZeroDivisionError as e:	
	print("不能除以0")	
else:
	print("代码没有报错才会执行")
	print("正常执行的代码的后面部分")
# 运行结果:
# 不能除以0

(三)、多异常类型的捕获

  • 多种异常出现时,可以统一处理的就用下面的方式一,处理方式不一样的就用方式二
方式一:
try:
	{'name':'yez'}['age']
	a = 1/0
	lst = ['yz','yr']
	lst[3]
except(ZeroDivisionError, IndexError, KeyError) as err:
  print(err)
	print('hello')  
except ImportError as e:
	print()
    
    
方式二:
try:
  {'name':'yez'}['age']
  a = 1/0
	lst = ['yz','yr']
	lst[3] 
except ZeroDivisionError as err:
	print(err)
except IndexError as err:
	print('index error')
except KeyError:
	print('key error')  

(四)、抛出异常

  • raise 主动抛出异常

    def adult_add(a, b):
      # 两个数相加, a, b 一定要大于18, 否则就不能运行
      if (a < 18) or (b < 18):
    		raise ValueError('参数必须大于18')
      c = a + b
      return c
    print(adult_add(3, 4))
    print('函数执行完成。')  # 上面一行报错,这行不会打
    
    try:
    	adult_add(3, 4)  
    except:
    	print('函数执行完成。')  # 结果会打印:函数执行完成。
    

(五)、断言 assert

  • 断言: assert

  • 断言的作用:判断真假

  • 断言的时候,如果断言成功,程序继续执行

  • 如果断言失败,程序终止运行,本质上断言失败会触发一个异常类型:AssertionError

  • 断言,主要用在预期结果和实际结果的比对

    height = int(input('输入身高:'))
    print(height > 180)  # False
    assert  height > 180
    print("断言有结果")
    

七、面向对象

(一)、类(Class)

  • 什么是类:

    • 是指所有符合某种特征的个体的集合
    • 类(Class) 是用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。
  • 类的表示:(下面三种写法作用完全一样)

    class 类名称:
        # 类当中的内容
        属性 ==》 特征
        行为
    
        
    class 类名称():
        pass
    
      
    class 类名称(object):
        pass
    
    
    class Dog:
        # 类内容
        tailed = True
    
        def say(self):
            print('汪汪。。。')
    
  • 类的命名

    • 符合标识符命名规则
    • 字母数字下划线,不能是关键字,要有意义
    • 规范:大驼峰,SingleDog
  • 使用 类 的好处

    • 方便复用(如果你用函数写,就要复制整块代码,增加了代码量,增加了出错率)
    • 方便扩展(函数写段代码,若要升级、扩展,都十分复杂,容易出错,用类来扩展,则方便清晰)
    • 方便维护(因为类是把抽象的东西映射成我们常见的,摸得到的东西,容易理解,维护也方便)

(二)、对象

  • 什么是对象:

    • 对象指的是某个类当中的一个成员,一个个体
    • 对象是从类当中生成的, ==》 类是一个模型,是一个生产图纸。
    • 对象就是类的具体实例
      • 类是函数的定义,对象是函数的调用
      • 实例、对象、object 都是同一个东西
    class Dog:
        # 类内容
        tailed = True
    
        def say(self):
            print('汪汪。。。')
            
    zhonghua = Dog() 
    print(zhonghua) # 是对象  <__main__.Dog object at 0x00000000022724A8>
    print(Dog) # 是类  <class '__main__.Dog'>
    
    # Dog 不加括号的时候是类
    zhonghua = Dog
    print(zhonghua) # <class '__main__.Dog'>
    

(三)、属性和方法

  • 属性就是指类或者对象的特征。名词
  • 方法就是指类或者对象的行为。动词
  • 属性:
    • 类属性(类变量):类当中每一个成员都具备的特征,类和对象都可以获取类属性
    • 实例属性(实例变量)、对象属性:类当中的成员不一定都具备的特征,是对象独有的,自己具备
  • 方法:
    • 类方法:每一个成员或者整个类都能调用的行为

    • 实例方法、对象方法:只能是需要一个单独的成员调用的行为,不能是整个类调用

      • 不要用整个类去调用实例方法
      • 实例方法在定义的时候自带一个参数:self,
      • 但是实例方法在调用的时候不需要传 self 这个参数的实际参数
      class Dog:
          # 有尾巴
          # 类属性
          tailed = True
      
          # 实例方法
          def say(self):
              print('汪汪汪。。。')
      
      # 对象
      teddy = Dog()
      
      # 类属性的获取
      print(Dog.tailed) # True
      
      # 对象获取属性
      print(teddy.tailed) # True
      
      # 属性可以后天修改
      Dog.tailed = False
      print(Dog.tailed) # False
      print(teddy.tailed) # False
      
      teddy.tailed = '有时候有尾巴,有时候没有'
      print(Dog.tailed) # False
      print(teddy.tailed) # 有时候有尾巴,有时候没有
      
      
      # 类方法的调用
      # Dog.say() # 会报错
      # Dog.say('abc') # 不要用整个类去调用实例方法
      # teddy.say('abc') # 会报错
      teddy.say() # 汪汪汪。。。
      

(四)、对象的初始化

  • 一个对象:除了整个类都具备的属性,还有自己的特征。 对象自己的特征就叫实例属性或者对象属性。

  • 每个对象都有自己不同的实例属性,可以在对象生成的时候传入实际参数,这个实际参数就是实例属性,传入实际参数时需要有对应的形式参数,这些形式参数不能在类后面直接定义,这里就定义了一个特别函数,方法,_init_,在这里面定义好的形式参数,最终在对象初始化的时候传入实际参数,这个实例属性产生的过程就叫对象的初始化。

  • 传入的实际参数是在什么时候调用的???

    teddy = Dog(name = ‘teddy’, color = ‘blue’) 自动调用 _init_
    不需要写 Dog._init_()

    TODO: 一定不要写成 _int_

    class Dog:
    
        tailed = True
    
        # 定义一个特别函数,方法,定义好的形式参数,最终在对象初始化的时候传入实际参数
        def __init__(self, name, color):
            """初始化函数,初始化方法"""
            # 自定义对象产生的过程
            # 实例属性的产生 self.name 定义一个叫做 name 的实例属性
            self.name = name
            self.color = color
        def say(self):
            print('汪汪汪。。。')
    
    teddy = Dog(name = 'teddy', color = 'blue')
    teddy.say()
    
    # 获取实例属性
    print(teddy.color)
    
    # 类不能调用实例属性
    # print(Dog.color)  # AttributeError: type object 'Dog' has no attribute 'color'
    

  • 实例化

    • 通过一个类去创建一个对象,就是实例化。

    • 实例化是产生对象的过程

    • 实例化就是函数的调用

    • 产生对象,实例化对象的时候,会自动调用 _init_ 这个方法

      self.name = name

      self.name ==> 实例属性

      name ====> 参数, teddy 值。

      name 这个name是变量,和类和对象没有关系

  • 什么是 self :

    • 所谓的self,可以理解为自己,就是我们的实例本身,代表实例对象,谁去调用代表谁。

      Kitty 这个实例对象调用,self就代表Kitty

      jingel 这个实例对象去调用,self就代表jingel

    • 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给 self,只需要传递后面的参数即可

    • self 可以改成其他名字,但不建议改,你改了别人就不知道具体的含义了

    class Dog:
    
        tailed = True
    
        # 定义一个特别函数,方法,定义好的形式参数,最终在对象初始化的时候传入实际参数
    
        def __init__(self, name, color='grey'):
            """初始化函数,初始化方法"""
            # 自定义对象产生的过程
            # 实例属性的产生 self.name 定义一个叫做 name 的实例属性
    
            # dog.name = name # 不能这样写,函数里面不能使用全局变量,这个时候 dog 这个对象还没有产生出来
            # Dog.name = name # 也不能这么写,不能所有的狗都叫同一个名字
    
            self.name = name
            self.color = color
            print(self)
    
        def say(self):
            print('汪汪汪。。。')
    
    dog = Dog('teddy')
    print(dog.color)  # grey
    # dog
    print(dog) # self 和 dog 对象是同一个地址
    
    
    # ha = Dog('teddy')
    # print(ha.color)  # grey
    # # dog
    # print(ha) # self 和 ha 对象是同一个地址
    

(五)、实例方法、类方法、静态方法

1、实例方法:

  • 定义:
    • 实例方法直接定义在类中
    • 第一个参数是 self (必须要写),
  • 实例方法的访问
    • 只有该类的实例对象都可以访问,访问实例方法的时候会自动将对象本身当成参数,传给self接收
  • 在类和对象当中,实例方法是用的最多的。
  • 如果不知道该定义成实例方法,类方法还是静态方法,就定义成实例方法
  • 调用方法:
    • obj.方法名()
    • 实例.方法()

2、类方法:

  • 定义:

    使用装饰器 @classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)

  • 调用:

    • 实例对象和类对象都可以调用
  • 应用场景:

    • 需要站在类的角度执行某个行为时,那么就应该定义为类方法
  • 类方法调用

    • 类.类方法()

3、静态方法:

  • 定义:

    • 使用装饰器 @staticmethod 参数随意,没有 self 和 cls 参数,但是方法体中不能使用类或实例的任何属性和方法
  • 调用:

    • 实例对象和类对象都可以调用。
  • 应用场景:

    • 存放逻辑代码,内部不需要引用类属性和实例属性
    • 当想在一个类当中定义一个方法,和这个类或者对象没有直接的关系。
    • 你在方法当中,没有使用到类或者是对象。
  • 静态方法调用:

    • 类和对象,都可以调用静态方法
  • 静态方法存在的理由:

    • 放在类里面方便管理

def say_static(times): # 放在这里是普通的函数,和放在类里面效果是一样的,只是调用时这个直接调用,调用类里面的需要加前缀
    print(f'汪汪。。。{times} 声')

class Dog:

    tailed = True

    # 定义一个特别函数,方法,定义好的形式参数,最终在对象初始化的时候传入实际参数

    def __init__(self, name, color='grey'):
        """初始化函数,初始化方法"""
        self.name = name
        self.color = color
        print(self)

    # 实例方法
    def say(self, times):
        print(f'{self}汪汪汪。。。{times} 声')

    # 静态方法
    @staticmethod
    def say_static(times):
        print(f'汪汪汪。。。{times} 声')
        

    # # 类方法。进化
    # def jinhua(self):
    #     print('狗类正在进化')
    #     Dog.tailed = False

    # 声明:这是一个类方法
    # 固定写法
    @classmethod
    def jinhua(cls):
        print('狗类正在进化')
        Dog.tailed = False


haha = Dog('haha')
yiyi = Dog('yiyi')
# print(haha.tailed) # F
# print(yiyi.tailed) # F

# Dog.jinhua() # jinhua()是实例方法,不能使用类去调用
# print(haha.tailed)
# print(yiyi.tailed)


# 类方法的调用
# Dog.jinhua()  # Dog 加括号表示对象,不加括号表示类
# haha.tailed


# haha.jinhua()
# print(haha.tailed)
#
# haha.say(5)


# 静态方法的调用,类和对象,都可以调用静态方法
haha.say_static(5)
Dog.say_static(6)

# 普通函数版
say_static(7)

(六)、继承

(1)、类的继承

  • 定义类两种方式的区别:

    # Python2 中称为经典类,在python3 中默认继承 object
    class MyTest:
        pass
    
    # python2 中称为新式类。
    class MyTest(object):
        pass
    # 注意点:python3 中上面两种定义方法没有区别,都是继承 object 这个父类
    
  • 在python3 的继承中,所有的类都默认继承自 object 这个基类。

  • 子类通过继承可以获得父类的属性和方法。

  • 被继承的类叫父类(也叫基类),继承的类叫子类

  • 注意:私有属性不能继承

  • 作用:

    • 子类通过继承可以获得父类的属性和方法,提高开发的效率及代码的复用率
    # 普通写法定义手机类和智能手机类
    class Mobile:
        def __init__(self, model, color='blacd'):
            self.model = model
            self.color = color
    
        def call(self):
            """打电话"""
            print(f"{self} 手机正在打电话。")
    
    
    class SmartPhone:
        def __init__(self, model, color='blacd'):
            self.model = model
            self.color = color
    
        def call(self):
            """打电话"""
            print(f"{self} 手机正在打电话。")
    
        def play_game(self):
            print("玩游戏")
    
    
    
    # 使用继承
    class Mobile():
        def __init__(self, brand, model, color='blacd'):
            self.model = model
            self.color = color
            self.brand = brand
    
        def call(self):
            """打电话"""
            print(f"{self} 手机正在打电话。")
    
    
    class SmartPhone(Mobile):
    
        def play_game(self):
            print("玩游戏")
    
    
    # iphone = SmartPhone()
    # iphone.play_game() # 这里会报错,初始化的时候需要调用__init__方法,自己没有去找父类,父类的__init__需要传参数
    
    iphone = SmartPhone('iphone12', 'apple')
    iphone.play_game()
    
    
    ​
    
    

(2)、超继承

  • 重写父类方法

    • 重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中的同名方法
    • 如:同样是打电话,第一版手机只能大语音电话,最新版手机可以打视频电话
  • 调用重名的父类方法

    • 子类重写了父类的方法之后,如何在子类中再调用父类的方法:
      • 方式一:父类名.方法名(self)
      • 方式二:super().方法名()
    class Mobile():
        def __init__(self, brand, model, color='blacd'):
            self.model = model
            self.color = color
            self.brand = brand
    
        def call(self):
            """打电话"""
            print(f"{self} 手机正在打电话。")
    
    
    class SmartPhone(Mobile):
        def __init__(self, model, brand, color='red', pixel = 2000):
            # self.model = model
            # self.color = color
            # self.brand = brand  # 这三行代码父类中有,可以使用 super()
            super().__init__(brand, model, color) # 使用 super() 直接调用父类的方法
            self.fiveG = True
            self.pixel = pixel
    
        def play_game(self):
            print("玩游戏")
    
        def call(self):
            """智能手机打电话"""
            print('开视频')
            super().call()
    
    # super 函数的使用
    smart = SmartPhone('p40','huawei')
    print(smart.pixel)
    smart.call()
    
    
    

(七)、动态获取属性

  • 获取对象属性的时候,如果对象中没有这个属性,代码就会报错

  • 可以使用 getattr( 对象, 属性名称 , 默认值) 动态获取属性,并在属性后面传入一个默认值,如果对象没有这个属性就会显示默认值,代码就不会报错

  • 还可以动态修改属性,使用 setattr( 对象, 属性名称 , 属性值)

    class Mobile:
    
        def __init__(self, brand, model):
            # 先天初始化过程中形成的属性
            self.brand = brand
            self.model = model
    
        def call(self):
            print('正在打电话。。')
    
    iphone = Mobile('apple', 'xr')
    # 获取属性
    # print(iphone.brand)
    # 修改属性
    # iphone.brand = 'aple'
    
    # 定义新的实例属性
    # 后天养成的特性
    # iphone.video = '美颜'
    # print(iphone.video)
    
    # 获取一个不存在的属性
    # 如果获取不存在的属性,代码会报错
    # print(iphone.games)  # AttributeError: 'Mobile' object has no attribute 'games'
    
    # 动态获取属性
    # getattr 内置函数
    
    # print(getattr(iphone, 'games')) # 还是报错:AttributeError: 'Mobile' object has no attribute 'games'
    # default ,如果获取不到属性名,传入 default 默认值,就不会报错了
    # getattr 不会修改原来的对象的属性
    print(getattr(iphone, 'games', '吃鸡'))
    
    # print(iphone.games,) # 还是会报错,因为iphone 没有games属性
    
    # 动态修改属性
    setattr(iphone, 'games', '王者荣耀')
    print(iphone.games) # 王者荣耀
    
Tags: