马士兵Python

Python入门 – 学完课程之后做的笔记(2022.10.15)

【花了2万多买的Python教程全套,现在分享给大家,入门到精通(Python全栈开发教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS?p=22&share_source=copy_web&vd_source=3429044f238c104ecc668f383c49499c

输出函数print()

  • 输入内容

    # 1. 输出数字
    print(3.1415);
    
    # 2. 输出字符串,三种引号都可以代表字符串
    print('hello, python');
    print("hello, world");
    print("""hello, print""")
    
    # 3. 输出含有运算符的表达式,会计算后输出计算结果
    print(1 + 1);
    
    # 4. 将数据输出到文件中
    # 注意,1. open()的第一个参数是 文件夹名 + 文件名,其中文件夹名必须存在,否则报错
    #      2. open()的第二个参数: a+ 的意思是 如果文件不存在就新建文件,存在则在该文件的末尾继续追加内容
    # 扩展:打开文件时,可指定 读取模式('r')、写入模式('w')、附加模式('a')或者能读取和写入文件的模式('r+')。
    #      如果省略了模式实参,Python将以默认的只读模式打开文件
    fp = open("D:/pythonTemp/test.txt", "a+");
    print("hello, file", file = fp);
    fp.close();
    
    # 5. 输出多句话不换行
    print("你好!", "换行了吗?", "没换行吧", "确实没换行");
    
  • 转义字符和原字符

    # \n : 换行
    print('hello,\nworld');
    
    # \t : 制表符
    # 注意,下面两个\t产生的空格数量并不相同
    # 原因是:\t 的原理是将字符串每四个字符一组,\t的位置之前的一组如果不满四个字符,则用空格填补成四个字符,
    # 如第一个print(),hell 是第一组,第二组只有 “o,”两个字符,所以\t的效果是填补两个空格
    # 而第二个print(),在 \t 前的一组已经满了,所以\t产生了四个空格,即一组
    print('hello,\tworld');			# hell-o,__-worl-d
    print('hello,oo\t,world');		# hell-o,oo-____-,wor-ld
    
    # \r : 覆盖前面的字符
    # \r后面的 world 覆盖了\r前面的 helloooo,
    print('helloooo, \rworld');		# 输出:world
    
    # \b : 退格,只退一格
    print('hello,\bworld');			# 输出:helloworld
    
    # \ 只是转义,无特殊功能
    print('http:\\\\www.baidu.com');
    print('He say: \'hello, everyone.\'');
    
    # 原字符,不希望字符串中的转义字符起作用,就使用原字符,
    # 使用方法:在字符串的前面加上 r 或 R
    # 注意:最后一个字符不能是 \
    print(r'hello, \rworld');
    # 最后面有偶数个 \ 不会报错
    print(R'hello, world\\');
    

变量

  • 保留字

    # 1.保留字
    # 通过以下代码,可以查看python的保留字列表
    import keyword
    print(keyword.kwlist)
    
  • 变量命名规则

    1. 字母、数字、下划线_
    2. 不能以数字开头
    3. 不能使用保留字
    4. 严格区分大小写
  • 变量由三部分组成

    • 标识:表示对象所存储的内存地址,使用内置函数 id(obj) 来获取

    • 类型: 表示对象的数据类型,使用内置函数 type(obj) 来获取

    • 值:表示对象所存储的具体数据

      # 2. 变量的组成
      name = "zhangsan"
      print(id(name))         # 1870083052912
      print(type(name))       # <class 'str'>
      print(name)             # zhangsan
      

数据类型

  • 常用的数据类型

    • 整数类型: int
    • 浮点数类型:float
    • 布尔类型:bool (注意,不是boolean)
    • 字符串类型:str (不是string)
  • 整数类型

    # 1. 整数类型
    # 可以表示正整数,负整数,0
    # int age = 19  这句代码会报语法错误,不能这样定义变量
    age = 19
    print(age)
    
    # 整数可以表示为二进制、十进制、八进制、十六进制
    # 输出时自动转成了十进制
    print('十进制', 18)
    print('二进制', 0b1011001)     # 二进制以 0b 开头,输出:89
    print('八进制', 0o176)         # 八进制以 0o 开头,输出:126
    print('十六进制', 0x1EAF)       # 十六进制以 0x开头,输出:7855
    
  • 浮点数类型

    # 2. 浮点数类型
    # 浮点数由整数部分和小数部分组成
    pi = 3.14159262
    print(pi)
    # 浮点数存储不精确性
    # 浮点数进行计算时,可能会出现小数位数不确定的情况
    print(1.1 + 2.2)        # 输出:3.3000000000000003
    print(1.1 + 2.1)        # 输出:3.2
    
    # 解决方案:导入模块decimal
    from decimal import Decimal
    print(Decimal('1.1') + Decimal('2.2'))      # 输出:3.3
    
  • 布尔类型

    # 3. 布尔类型
    # 用来表示真或假
    print(type(True))       # 输出:<class 'bool'>
    # 布尔值可以转化为整数,True -> 1, False -> 0
    print(True + 1)         # 输出:2
    print(False + 1)        # 输出:1
    
  • 字符串类型

    # 4. 字符串类型
    # 字符串是不可变的字符序列
    name = "zhangsan"
    print(id(name))             # 输出:2865920795248
    username = "zhangsan"
    print(id(username))         # 输出:2865920795248
    
    # 可以使用单引号,双引号,三引号来定义字符串
    # 三引号定义的字符串可以分布在连续的多行
    print('hello, python')      # 不可换行
    print("hello, python")      # 不可换行
    print("""hello,
    python""")              # 相当于 print("hello, \npython")
    
  • 类型转换

    • str()

      # 1. int -> str
      age = 19
      # print("我今年" + age + "岁")        # 报错:TypeError: can only concatenate str (not "int") to str
      print("我今年" + str(age) + "岁")     # 输出成功
      
      # 2. float -> str
      print(str(3.14), type(str(3.14)))   # 输出:3.14 <class 'str'>
      # 3. bool -> str
      print(str(True), type(str(True)))   # 输出:True <class 'str'>
      
    • int()

      # 整型字符串 -> int
      num = "123"
      print(int(num), type(int(num)))             # 输出:123 <class 'int'>
      
      # 只有整型字符串可以通过int()转换成整型
      # bool字符串无法转换成整型
      print(int("True"), type(int("True")))       # invalid literal for int() with base 10: 'True'
      # 浮点数字符串无法转换成整型
      f = '3.14'
      print(int(f), type(int(f)))                 # invalid literal for int() with base 10: '3.14'
      # 非数字型字符串无法转换成整型
      print(int("hello"), type(int("hello")))     # invalid literal for int() with base 10: 'hello'
      
      # float -> int
      # 截取整数部分
      print(int(3.14), type(int(3.14)))           # 输出:3 <class 'int'>
      
      # bool -> int
      # True: 1, False: 0
      print(int(True), type(int(True)))           # 输出:1 <class 'int'>
      
    • float()

      # 3. float()
      # str -> float
      print(float(3.14), type(float(3.14)))           # 输出:3.14 <class 'float'>
      print(float(4), type(float(4)))                 # 输出:4.0 <class 'float'>
      # 非数字字符串无法转换为float
      print(float("hello"), type(float("hello")))     # could not convert string to float: 'hello'
      
      # int -> float
      print(float(6), type(float(6)))                 # 输出:6.0 <class 'float'>
      
      # bool -> float
      print(float(True), type(float(True)))           # 输出:1.0 <class 'float'>
      

注释

  • 单行注释:以 # 开头,直到换行结束

  • 多行注释:并没有单独的多行注释标记,将一对三引号之间的代码称为多行注释

    # 这是单行注释
    """
    这
    是
    多行
    注释
    """
    

输入函数input()

# input()输出括号内的值,并返回用户输入的值,返回值是str类型
age = input("你今年多少岁了")
print(age, type(age))       # 输出:18 <class 'str'>

print("请输入两个加数,我来计算它们的和。")
print(int(input("第一个加数:")) + int(input("第二个加数:")))

运算符

  1. 算术运算符

    print(1 + 1)        # 加法
    print(1 - 1)        # 减法
    print(2 * 4)        # 乘法
    print(10 / 3)       # 除法,正常的除法。 输出:3.3333333333333335
    print(10 // 3)      # 整除。       输出:3
    print(11 % 2)       # 取余         输出:1
    print(2 ** 3)       # 幂,表示2的3次方
    
    print("--------------------------------")
    # 特殊情况
    # 整除 //
    # 同符号情况,正常
    print(9 // 4)       # 2
    print(-9 // -4)     # 2
    # 一正一负的情况
    # 这种情况下,结果需要向下取整,9除以-4的结果是-2.2,向下取整,所以结果是-3
    print(9 // -4)      # -3
    print(-9 // 4)      # -3
    
    print("--------------------------------")
    # 取余 %
    # 同符号情况,正常
    print(9 % 4)        # 1
    print(-9 % -4)      # -1
    
    # 一正一负的情况
    # 余数 = 被除数 - (除数 * (被除数 // 除数))
    # 余数 = 9 - (-4 * (9 // -4)) = 9 - (-4) * (-3) = 9 - 12 = -3
    print(9 % -4)       # -3
    print(-9 % 4)       # 3
    
  2. 赋值运算符

    # 赋值运算符
    # 1. 赋值执行顺序:右 -> 左
    a = 3 + 4
    print(a)        # 7, 先右边运算,然后赋值给左边的变量
    
    # 2. 支持链式赋值
    a = b = c = 20
    print(a, id(a))     # 20 2172753019728
    print(b, id(b))     # 20 2172753019728
    print(c, id(c))     # 20 2172753019728
    
    # 3. 支持参数赋值: +=,-=,*=,/=,//=,%=
    num = 10
    num /= 2
    print(num)
    
    # 4. 支持系列解包赋值
    a, b, c = 10, 20, 30
    print(a, b, c)      # 10 20 30
    # 解包赋值可以使得两个变量交换值不需要临时变量
    a, b = b, a
    print(a, b)         # 20 10
    # 传统做法
    temp = a
    a = b
    b = temp
    print(a, b)
    
  3. 比较运算符

    # 比较运算符,返回结果为bool类型
    # 1. >,<,>=,<=,!=
    print(10 <= 20)     # True
    print(10 != 20)     # True
    
    # 2. ==
    print(10 == 20)     # False
    
    # == 比较的是对象的value值
    a = 10
    b = 10
    print(a == b)       # True
    
    print("--------------------------------")
    # 3. is,is not 相同,不相同
    # is, is not 比较的是对象的id
    a = 10
    b = 10
    print(a is b)       # True
    
    list1 = [1, 2, 3, 4]
    list2 = [5, 6, 7, 8]
    print(list1 is list2)       # False
    print(id(list1))            # id: 1403208193216
    print(id(list2))            # id: 1403499526848
    
  4. 布尔运算符

    # and 与运算
    print(1 < 2 and 2 > 3)      # False
    
    # or 或运算
    print(1 < 2 or 2 > 3)       # True
    
    # not 非运算
    print(not 1 < 2)            # False
    
    # in, not in
    s = "hello, world"
    print('w' in s)         # True
    print('k' not in s)     # True
    
    list = [1, 2, 3]
    print(1 in list)        # True
    
  5. 位运算符

    # 位运算:将数据转成二进制进行计算
    # 1. 位与 &
    # 对应数位都是1,结果位数才是1,否则为0
    # 4 ->  00000100
    # 8 ->  00001000
    # & ->  00000000  --> 0
    
    print(4 & 8)        # 0
    
    # 2. 位或 |
    # 对应数位都是0,结果数位才是0,否则为1
    # | ->  00001100  --> 12
    print(4 | 8)        # 12
    
    # 3. 左移位运算符 <<
    # 每左移 1 相当于乘以 2
    print(4 << 2)       # 结果:16, 4 * 2 * 2
    
    # 4. 右移位运算符 >>
    # 相当于除以2
    print(4 >> 2)       # 结果:1, 4 // 2 // 2
    
  6. 运算符优先级

    ()括号 -> 算术运算符(先幂,后乘除,再加减) -> 位运算符(先左移右移,再位与,位或) -> 比较运算符(>,<,>=,<=,==,!=) -> 布尔运算符(and,or) -> 赋值运算符

分支语句

  • 对象的布尔值

    • Python中,所有对象都有一个布尔值,可以通过内置函数 **bool()**获取对象的布尔值

    • 以下对象的布尔值为False

      print(bool(False))          # False, 布尔类型False
      print(bool(0))              # False, 数值0
      print(bool(0.0))            # False, 数值0.0
      print(bool(None))           # False, None
      print(bool(""))             # False, 空字符串
      print(bool([]))             # False, 空列表
      print(bool(list()))         # False, 空列表
      print(bool(()))             # False, 空元组
      print(bool(tuple()))        # False, 空元组
      print(bool({}))             # False, 空字典
      print(bool(dict()))         # False, 空字典
      print(bool(set()))          # False, 空集合
      
  • if - elif - else

    score = int(input("请输入你的成绩:"))
    # 在python中,score >= 90 and score <= 100 可以写成:90 <= score <= 100
    if 90 <= score <= 100 :
        print("你的成绩等级是:A+")
    elif 80 <= score < 90 :
        print("你的成绩等级是:A")
    elif 70 <= score < 80 :
        print("你的成绩等级是:A-")
    elif 60 <= score < 70 :
        print("你的成绩等级是:B")
    elif 0 <= score < 60 :
        print("你的成绩等级是:C,成绩不合格,请继续努力")
    else :
        print("请输入正确的成绩!")
    
  • 条件表达式

    • 条件表达式是 if - else 的简写
    • 语法结构:
      • x if 判断条件 else y
    • 运算规则:
      • 如果判断条件的布尔值为 True,条件表达式的返回值为 x,否则条件表达式的返回值为 False
    print("请输入两个整数,我来比较它们的大小。")
    num1 = input("第一个数为: ")
    num2 = input("第二个数为: ")
    
    # 普通版
    # if int(num1) > int(num2) :
    #     print(num1 + "大于" + num2)
    # else :
    #     print(num1 + "小于" + num2)
    
    # 简化版
    print(num1 + "大于" + num2 if int(num1) > int(num2) else num1 + "小于" + num2)
    
  • pass语句

    • 这个语句什么都不做,只是一个占位符,用在语法上需要语句的地方

      list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      sum = 0
      for i in list :
          # 此处的if语句没有任何作用
          if i % 2 :
              pass
          sum += i
      
      print(sum)      # 55
      

循环语句

  • range()函数

    • 用于生成一个整数序列

    • 创建range对象的三种方式

      # 1. range(stop) -> 创建一个 [0, stop) 之间的整数序列,步长为默认值 1
      print(range(10))        # 输出:range(0, 10)
      
      # range()的返回值是一个迭代器对象,如果想得到序列,需要通过 list(range())获得
      list1 = list(range(10))
      print(list1)        # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      # 2. range(start, stop) -> 创建一个 [start, stop) 之间的整数序列,步长为默认值 1
      list2 = list(range(1, 10))
      print(list2)        # [1, 2, 3, 4, 5, 6, 7, 8, 9]
      
      # 3. range(start, stop, step) -> 创建一个 [start, stop) 之间的整数序列,步长为 step
      list3 = list(range(0, 10, 2))
      print(list3)        # [0, 2, 4, 6, 8]
      
    • 优点:

      • 不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的,因为只需要存储start,stop,step。
      • 只有当用到range对象时,才会去计算序列中的相关元素
  • while循环语句

    # 使用while计算100以内偶数和
    i = 0
    sum = 0
    while i < 100 :
        sum += i
        i += 2
    
    print("100以内的偶数和为:" + str(sum))
    
  • for - in 循环语句

    # 遍历字符串
    for item in "Python" :
        print(item)
    
    # range() 产生一个整数序列,也是一个可迭代对象
    for i in range(100) :
        print(i)
    
    # 如果循环体中不需要使用自定义变量,可以将自定义变量写为 ”_“
    for _ in range(5) :
        print("hello!")
    
    # 使用for-in 计算100以内偶数和
    sum = 0
    for i in range(0, 100, 2) :
        sum += i
    
    print("100以内的偶数和为:" + str(sum))
    
  • 练习:输出100到999之间的水仙花数

    # 水仙花数:一个数的每位数的三次方之和等于这个数,如:153 = 3*3*3 + 5*5*5 + 1*1*1
    # 循环次数确定,所以使用for-in循环语句
    # num = 153
    # 个位数
    # x = num % 10
    # 十位数
    # y = (num // 10) % 10
    # 百位数
    # z = num // 100
    # print(x)
    # print(y)
    # print(z)
    for num in range(100, 1000) :
        x = num % 10
        y = (num // 10) % 10
        z = num // 100
        if num == x**3 + y**3 + z**3 :
            print(num)
    
  • break 和 continue

    print("你输入一些数,我来计算这些数里面的偶数和")
    print("输入q终止输入")
    sum = 0
    while True:
        num = input("请输入:")
        
        """ 如果输入 q ,通过 break 退出循环"""
        if num == "q" :
            print("这些数里面的偶数和为:" + str(sum))
            break
            
        """ 如果输入的数不是偶数,通过 continue 结束本次循环""" 
        if int(num) % 2 != 0:
            continue
        sum += int(num)
    
  • else的其他用法

    • 与else语句配合使用的三种情况

      1. 搭配 if ,当 if 条件表达式不成立时执行 else
      2. 搭配 while ,当没有碰到 break 时执行 else,也就是循环正常结束时执行
      3. 搭配 for ,同 搭配 while
      # 与else语句搭配使用的三种情况
      
      # 1. 搭配 if
      if int(input("请输入一个数: ")) % 2 == 0 :
          print("这个数是个偶数")
      else :
          print("这个数是个奇数")
      
      # 2. 搭配 while
      i = 0
      while i < 3 :
          if input("请输入密码: ") == "123456" :
              print("密码正确,登录成功")
              break
          print("密码错误,请重新输入")
          i += 1
      else :
          print("3次密码输入错误,请等候15分钟后重新输入")
      
      # 3. 搭配 for
      for i in range(3) :
          if input("请输入密码: ") == "123456" :
              print("密码正确,登录成功")
              break
          print("密码错误,请重新输入")
      else :
          print("3次密码输入错误,请等候15分钟后重新输入")
      
  • 练习:使用双重循环打印9*9乘法表

    for i in range(1, 10) :
        for j in range(1, i+1) :
            # 第二个字符串使用:end="\t" 来让print()以制表符结尾,而不是换行符结尾
            print(j, "*", i, "=", i*j, end="\t")
        print()
    

列表

  • 列表的创建

    1. 使用中括号

    2. 调用内置函数 list()

      # 1. 列表的创建
      # 使用中括号创建
      list1 = ["hello", "python", 29];
      
      # 使用 list() 函数创建
      list2 = list(["world", "zhangsan", 82])
      
  • 列表的特点

    1. 元素按顺序有序排序
    2. 索引映射唯一一个数据
    3. 可存储重复数据
    4. 任意数据类型混存
    5. 根据需要动态分配和回收内存
  • 查询

    # 1. 通过value获取index -> index()函数
    language = ["C", "C++", "Java", "JavaScript", "Python", "Go", "Java"]
    # 如果列表中存在N个相同的元素,只返回相同元素中的第一个元素的索引
    print(language.index("Java"))       # 输出:2
    # 如果查询的元素在列表中不存在,则会抛出ValueError异常
    # print(language.index("C#"))         # ValueError: 'C#' is not in list
    # 可以在指定范围进行查找 -> index(value, start, end), 注意,不包括end索引
    print(language.index("Java", 3, 8))     # 6
    
    # 2. 通过index获取value -> list[index]
    # 正向索引:从 0 到 N-1
    print(language[2])                  # Java
    # 反向索引:从 -N 到 -1, 最后一个元素为 list[-1]
    print(language[-1])                 # Java
    # 指定索引不存在,抛出IndexError异常
    print(language[7])                  # IndexError: list index out of range
    
  • 切片

    # 切片语法格式:列表名[start:stop:step],切割的区间是[start, stop),不包括stop,步长为step
    # 1. 正向切
    nums = [11, 12, 13, 14, 15, 16, 17, 18, 19]
    print(nums[2:7:2])          # 输出:[13, 15, 17]
    # 默认值:start = 0,stop = N,step = 1
    print(nums[::])
    # 切片返回的是一个新列表
    # 可通过 nums[::] 复制列表
    print(id(nums))             # 2242914473152
    print(id(nums[::]))         # 2243206067648
    
    # 2. 反向切
    # 默认值:start = -1,stop = -N-1, step = -1, step必须是负数才能正常切片
    print(nums[-1:-8:-1])
    # 可通过 反向切片 来获取逆序列表片段
    print(nums[::-1])           # [19, 18, 17, 16, 15, 14, 13, 12, 11]
    
  • 遍历

    # 1. 判断指定元素在列表中是否存在
    # 已注册用户
    users = ["zhangsan", "lisi", "wangwu", "zhaoliu", "xiaoming"]
    # 登录用户
    user = "qianer"
    # 查看登录用户是否已注册
    print(user in users)        # 输出:False
    
    # 2. 遍历
    # 登录用户
    loginUsers = ["qianer", "wangwu", "zhaoyi", "xiaoming", "zhangsan"]
    # 查看登录用户中哪些是已注册用户
    for user in loginUsers:
        if user in users:
            print(user)
    
  • 添加元素

    # append() : 在列表末尾添加一个元素
    nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    nums.append(10)
    print(nums)
    # 是在原列表上添加
    print(id(nums))             # id: 1714674717888
    nums.append(11)
    print(id(nums))             # id: 1714674717888
    
    # extend() : 在列表末尾添加一个或多个元素
    nums2 = [12, 13]
    nums.extend(nums2)
    # 是在原列表上添加
    print(nums, id(nums))       # nums: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] id: 1714674717888
    
    # insert() : 在列表任意位置添加一个元素
    nums.insert(0, 20)
    print(nums, id(nums))       # nums: [20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], id: 1714674717888
    
    # 切片 : 在列表的任意位置添加至少一个元素
    nums[len(nums):] = [21, 22]
    # # 是在原列表上添加
    print(nums, id(nums))       # nums: [20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 22], id: 1714674717888
    
    # 会将nums[0]后面的元素全部截掉,然后添加[100, 101]
    nums[1:] = [100, 101]
    print(nums)                 # nums: [20, 100, 101]
    
  • 删除

    nums = [10, 20, 30, 40, 50, 60, 30]
    # 1. remove(value): 删除列表中值等于value的元素
    # 重复元素只删除第一个
    # 元素不存在抛出ValueError异常
    nums.remove(30)
    print(nums)             # [10, 20, 40, 50, 60, 30]
    
    # nums.remove(100)        # ValueError: list.remove(x): x not in list
    
    # 2. pop(index): 删除指定索引位置的元素
    # 如果索引不存在,抛出IndexError异常
    # 不指定索引,删除列表最后一个元素
    nums.pop(1)
    print(nums)               # [10, 40, 50, 60, 30]
    
    # nums.pop(100)           # IndexError: pop index out of range
    
    nums.pop()
    print(nums)               # [10, 40, 50, 60]
    
    # 3. 切片: 一次删除一个或多个元素, 不过,切片后返回的是新的列表
    # new_nums = nums[1:3]
    # print(new_nums)         # [40, 50]
    # print(id(nums))         # 1650795074752
    # print(id(new_nums))     # 1651086210496
    
    # 不产生新的列表对象,而是删除原列表中的内容
    print(id(nums))
    nums[1:3] = []
    print(nums)
    print(id(nums))
    
    # 4. clear(): 清空列表, 清空数据,不删除对象
    nums.clear()
    print(nums)               # []
    
    # 5. del: 删除列表,直接删除列表对象
    del nums
    print(nums)               # NameError: name 'nums' is not defined  
    
  • 修改

    nums = [10, 20, 30, 40, 50, 60]
    # 1. 一次修改一个值
    nums[2] = 100
    print(nums)                 # [10, 20, 100, 40, 50, 60]
    
    # 2. 修改多个值
    nums[1:3] = [200, 300, 400, 500]
    print(nums)                 # [10, 200, 300, 400, 500, 40, 50, 60]
    
  • 排序

    # 1. sort(): 列表的方法,对原列表操作,默认按从小到大的顺序排序
    nums = [12, 39, 48, 1, 22, 8, 93]
    print("排序前:", nums, id(nums))           # 排序前: [12, 39, 48, 1, 22, 8, 93] 2452120392896
    nums.sort()
    print("排序后:", nums, id(nums))           # 排序后: [1, 8, 12, 22, 39, 48, 93] 2452120392896
    
    # 通过参数reverse=True,实现降序排序
    nums. sort(reverse=True)
    print("降序排序:", nums)                    # 降序排序: [93, 48, 39, 22, 12, 8, 1]
    
    # 2. 内置函数sorted(): 产生一个新的列表,默认按从小到大排序
    # 也可通过参数reverse=True,进行降序排序
    new_nums = sorted(nums)
    print("内置函数排序:", new_nums, id(new_nums))    # 内置函数排序: [1, 8, 12, 22, 39, 48, 93]
    down_nums = sorted(nums, reverse=True)
    print("内置函数降序排序:", down_nums)              # 内置函数降序排序: [93, 48, 39, 22, 12, 8, 1]
    
  • 列表生成式

    # 列表生成式,简称“生成列表的公式”
    # 语法格式:
    #   [i for i in range()]
    nums = [i for i in range(1, 10)]
    print(nums)                 # [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 列表生成式的意思是,通过for-in循环遍历,并将遍历的每个 i 作为列表的元素
    # 还可以对 i 运算,并将运算后的结果作为列表的元素
    # 生成一个2,4,6, 8, 10的列表
    even_nums = [i*2 for i in range(1, 6)]
    print(even_nums)           # [2, 4, 6, 8, 10]
    

字典

  • 字典的创建

    # 1. 使用花括号创建
    # 键需要引号,值如果是字符串则需要引号,否则不用
    scores = {"张三" : 100, '李四' : 98, '小明' : 59}
    print(scores, type(scores))             # {'张三': 100, '李四': 98, '小明': 59} <class 'dict'>
    
    # 2. 内置函数 dict() 创建
    # 内置函数创建,键不用添加单引号
    students = dict(name='tomas', age=20, gender='male')    # {'name': 'tomas', 'age': 20, 'gender': 'male'}
    print(students)
    
    # 3. 空字典
    empty = {}
    print(empty)            # {}
    
  • 字典元素的获取

    # 1. []
    scores = {"张三" : 100, '李四' : 98, '小明' : 59}
    print(scores['张三'])         # 100
    
    # 2. get()方法
    print(scores.get('张三'))     # 100
    
    # [] 和 get()的区别
    # [] 如果字典中不存在指定的key,抛出KeyError异常
    print(scores['王五'])         # KeyError: '王五'
    
    # get() 如果字典中不存在指定的key,不抛出KeyError异常,而是返回None
    print(scores.get('王五'))     # None
    # 而且,可以通过参数设置默认的value,当指定的key不存在时返回该value
    print(scores.get('王五', 99)) # 99
    
  • 增删改

    # key的判断:in - not in
    scores = {"张三" : 100, '李四' : 98, '小明' : 59}
    print('张三' in scores)               # True
    print('author' not in scores)        # False
    
    # 增
    scores['author'] = 99
    print(scores)                       # {'张三': 100, '李四': 98, '小明': 59, 'author': 99}
    # 改
    scores['小明'] = 60
    print(scores['小明'])                 # 60
    
    # 删
    del scores['小明']                    # {'张三': 100, '李四': 98, 'author': 99}
    print(scores)
    
    # 清空
    scores.clear()
    print(scores)                       # {}
    
  • 字典的视图

    # 1. keys(): 获取字典中所有的key
    scores = {"张三" : 100, '李四' : 98, '小明' : 59}
    print(scores.keys())                # dict_keys(['张三', '李四', '小明'])
    print(type(scores.keys()))          # <class 'dict_keys'>
    print(list(scores.keys()))          # ['张三', '李四', '小明'], 通过list()可以得到字典所有key组成的列表
    
    # 2. values(): 获取字典中所有的value
    print(scores.values())              # dict_values([100, 98, 59])
    print(type(scores.values()))        # <class 'dict_values'>
    print(list(scores.values()))        # [100, 98, 59]
    
    # 3. items(): 获取字典中所有键值对
    print(scores.items())               # dict_items([('张三', 100), ('李四', 98), ('小明', 59)])
    print(type(scores.items()))         # <class 'dict_items'>
    print(list(scores.items()))         # [('张三', 100), ('李四', 98), ('小明', 59)], 通过list()可以得到 键值对元组 列表
    
  • 字典的遍历

    scores = {"张三" : 100, '李四' : 98, '小明' : 59}
    # item 为字典的键
    for item in scores:
        print(item, scores[item], scores.get(item))     # 张三 100 100  李四 98 98  小明 59 59
    
  • 字典的特点

    # 1. key不允许重复,value允许重复
    scores = {'张三': 100, '张三': 60}
    print(scores['张三'])             # 60, 当出现重复key时,后面的会覆盖前面的
    
    # 2. key必须是不可变对象,不能使用list作为key
    list = [1, 2, 3, 4]
    scores[list] = 86
    print(scores[list])             # TypeError: unhashable type: 'list'
    
    # 3. 元素是无序的
    # 4. 字典可以根据需要动态地伸缩
    # 5. 字典会浪费较大的内存,是一种空间换时间的数据结构
    
  • 字典的生成式

    users = ['zhangsan', 'lisi', 'wangwu']
    # age = [20, 23, 21]
    age = [20, 23, 21, 100, 1000]
    
    # 字典的生成式
    # 内置函数zip(): 用于将可迭代的对象(可遍历的对象)作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表
    # 如果两个可迭代对象的元素个数不同,会以元素个数少的为基准
    userInfo = {key.title(): value for key, value in zip(users, age)}
    print(userInfo)             # {'Zhangsan': 20, 'Lisi': 23, 'Wangwu': 21}
    

元组

  • 可变序列和不可变序列

    # 可变序列: 列表,字典
    # 可变序列可以对序列执行增删改操作,对象地址不发生更改
    nums = [1, 2, 3, 4]
    print(id(nums))         # 1729069044928
    nums.append(5)
    print(id(nums))         # 1729069044928
    
    # 不可变序列: 字符串,元组
    str = "hello"
    print(id(str))          # 1729360323504
    str += ", world"
    print(id(str))          # 1729350159408
    
  • 元组的创建

    # 1. 直接小括号 ()
    t = ('zhangsan', '20', 'male')
    print(t)
    
    # 2. 内置函数 tuple()
    t2 = tuple(('lisi', '21', 'female'))
    print(t2)
    print(type(t2))
    
    # 3. 只包含一个元组的元素需要使用逗号和小括号
    t3 = ('zhang',)
    t4 = ('zhangsan')
    print(type(t4))         # <class 'str'>
    
  • 元组的遍历

    person = ('zhangsan', 21, 'male')
    # 通过索引获取
    print(person[0])        # zhangsan
    print(person[1])        # 21
    print(person[2])        # male
    
    # 遍历元组
    for item in person:
        print(item)
    

集合

  • 集合的创建

    # 1. 通过 {} 创建
    set1 = {2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7}
    print(set1)         # {2, 3, 4, 5, 6, 7}, 集合中的元素不允许重复,会自动去重
    
    # 2. 内置函数 set()
    # range()
    set2 = set(range(5))
    print(set2)         # {0, 1, 2, 3, 4}
    
    # 列表
    set3 = set([1, 2, 3, 4, 2, 3, 5, 5, 6, 6])
    print(set3)         # {1, 2, 3, 4, 5, 6}
    
    # 元组
    set4 = set((3, 4,43, 121))
    print(set4)         # {43, 3, 4, 121}
    
    # 字符串
    set5 = set("Python")
    print(set5)         # {'o', 't', 'P', 'h', 'n', 'y'}, 这里可以看出,集合元素是无序的
    
    # 不可以用 {} 定义一个空集合,因为,{} 是字典
    s6 = {}
    print(type(s6))     # <class 'dict'>
    
    # 只能通过set()定义空集合
    s7 = set()
    print(type(s7))     # <class 'set'>
    
  • 集合的增删改

    # 1. in - not in
    set1 = {12, 39, 492, 43, 19, 594, 82}
    print(12 in set1)           # True
    print(999 not in set1)      # True
    
    # 2. 新增操作
    # add() 一次添加一个元素
    set1.add(999)
    print(999 not in set1)      # False
    
    # update() 一次添加至少一个元素, 参数必须是可迭代对象
    # set1.update(78, 87)
    print(set1)                 # TypeError: 'int' object is not iterable
    
    set1.update([78, 87])
    print(set1)                 # {12, 78, 594, 19, 82, 87, 999, 39, 43, 492}
    
    # 3. 删除操作
    # remove() 一次删除一个指定的元素,如果元素不存在,抛出KeyError异常
    set1.remove(12)
    print(12 in set1)           # False
    # set1.remove(13)             # KeyError: 13
    
    # discard() 一次删除一个指定的元素,如果元素不存在,不抛出异常
    set1.discard(13)
    
    # pop() 一次只删除一个任意元素,不可以添加参数
    set1.pop()
    print(set1)
    # set1.pop(19)                # TypeError: set.pop() takes no arguments (1 given)
    
    # clear() 清空集合
    set1.clear()
    print(set1)                 # set()
    
  • 集合间的关系

    # 相等:== != 进行判断
    set1 = {10, 20, 30, 40, 50}
    set2 = {10, 20, 30, 40, 50}
    print(set1 == set2)             # True
    
    # 子集:issubset()
    Father = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    Son = {1, 2, 3}
    print(Son.issubset(Father))     # True
    
    # 超集:issuperset()
    print(Father.issuperset(Son))   # True
    
    # 交集:isdisjoint()  注意:有交集,返回False, 无交集,返回True
    print(Son.isdisjoint(Father))   # False
    
    Mother = {20, 30, 40, 50}
    print(Father.isdisjoint(Mother))    # True
    
  • 集合的数学操作

    # 1. 交集  intersection()  &
    s1 = {1, 2, 3, 4, 5}
    s2 = {3, 4, 5, 6, 7}
    print(s1.intersection(s2))      # {3, 4, 5}
    print(s1 & s2)                  # intersection() 与 & (与)等价,交集操作
    
    # 2. 并集  union()  |
    print(s1.union(s2))             # {1, 2, 3, 4, 5, 6, 7}
    print(s1 | s2)                  # union() 与 | (或)等价
    
    # 3. 差集  difference()  -   差集是 s1 去除掉 s1 和 s2 的交集
    print(s1.difference(s2))        # {1, 2}
    print(s1 - s2)                  # difference() 与 - (减号)等价
    
    # 4. 对称差集  symmetric_difference()  ^   对称差集是 s1 和 s2 的并集 减去 s1 和 s2 的交集
    print(s1.symmetric_difference(s2))          # {1, 2, 6, 7}
    print(s1 ^ s2)                  # symmetric_difference() 与 ^ (按键6) 等价
    
  • 集合的生成式

    # 列表生成式
    list1 = [i * i for i in range(10)]
    print(list1)                            # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    # 集合生成式
    # 集合生成式只是将列表生成式的 [] 改成 {}
    set1 = {i * i for i in range(10)}
    print(set1)                             # {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
    

数据结构总结

  • image-20221025222614422

字符串

  • 字符串驻留机制

    • 仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量

    • 驻留机制的几种情况(交互模式,即windows的命令行模式中使用python)

      # 1. 字符串的长度为0或1时
      >>> a='a'
      >>> b='a'
      >>> a is b
      True
      
      # 2. 符合标识符的字符串(字母,数字,下划线组成)
      >>> a='abc%'	# % 不符合
      >>> b='abc%'
      >>> a is b
      False
      
      >>> a='abc_'
      >>> b='abc_'
      >>> a is b
      True
      
      # 3. 字符串只在编译时进行驻留,而非运行时
      >>> a='abc'
      >>> b='ab' + 'c'
      >>> c=''.join(['ab', 'c'])		# join() 为运行时
      >>> a is b
      True
      >>> a is c
      False
      
      # 4. [-5,  256]之间的整数数字
      >>> a=-5
      >>> b=-5
      >>> a is b
      True
      >>> a=-6
      >>> b=-6
      >>> a is b
      False
      
    • sys 模块中的 intern() 方法可以强制2个字符串指向同一个对象

      >>> import sys
      >>> a='abc%'
      >>> b='abc%'
      >>> a is b
      False
      >>> a=sys.intern(b)
      >>> a is b
      True
      
    • PyCharm 对字符串进行了优化处理,上述4中情况在PyCharm中不一定适合

      # 1. 对于条件1, 不适用
      a = '%%'
      b = '%%'
      print(a is b)                     # True
      
      # 2. 对于条件2,不适用
      a = 'aaaaaaaaaaaaaaaaaaaaaaaaaa'
      b = 'aaaaaaaaaaaaaaaaaaaaaaaaaa'
      print(a is b)                     # True
      
      # 3. 对于条件3,适用
      x = 'abc'
      y = 'ab' + 'c'
      z = ''.join(['ab', 'c'])
      print(x is y)                   # True
      print(x is z)                   # False
      
      # 4. 对于条件4,不适用
      num1 = -9999
      num2 = -9999
      print(num1 is num2)             # True
      
    • 在需要进行字符串拼接时,建议使用 str 类型的 join() 方法,而非 + ,因为 join() 方法是先计算出所有字符中的长度,然后再拷贝,只 new 一次对象,效率要比 + 效率高

  • 字符串的查找

    # 1. index(substr)  查找子串 substr 第一次 出现的位置,如果查找的子串不存在,抛出 ValueError 异常
    str1 = "hello, hello"
    print(str1.index("lo"))         # 3, 返回 l 所在的索引
    # print(str1.index("hi"))         # ValueError: substring not found
    
    # 2. rindex(substr) 查找子串 substr 最后一次 出现的位置,如果查找的子串不存在,抛出 ValueError 异常
    print(str1.rindex("lo"))        # 10
    # print(str1.rindex("hi"))        # ValueError: substring not found
    
    # 推荐使用 find() 和 rfind() 查找字符串
    # 3. find(substr)  查找子串 substr 第一次 出现的位置,如果查找的子串不存在,返回 -1
    print(str1.find("lo"))          # 3
    print(str1.find("k"))           # -1
    
    # rfind(substr)  查找子串 substr 最后一次 出现的位置,如果查找的子串不存在,返回 -1
    print(str1.rfind("lo"))         # 10
    print(str1.rfind("hi"))         # -1
    
  • 字符串的大小写操作

    str1 = "hello, World"
    
    # 1. upper(): 把字符串中所有字符都转成 大写 字母
    upperStr = str1.upper()         # 返回一个新的字符串对象
    print(upperStr)                 # HELLO, WORLD
    
    # 2. lower(): 把字符串中所有字符都转成 小写 字母
    lowerStr = str1.lower()
    print(lowerStr)                 # hello, world
    
    # 3. swapcase(): 把字符串中所有 大写 字母 转成 小写,把 小写 转成 大写
    swapcaseStr = str1.swapcase()
    print(swapcaseStr)              # HELLO, wORLD
    
    # 4. capitalize(): 把 第一个 字符转换成大写,其余的转换为小写
    capitalizeStr = str1.capitalize()
    print(capitalizeStr)            # Hello, world
    
    # 5. title(): 把每个单词的 第一个字符转换为 大写,把每个单词 剩余字符转换为 小写
    titleStr = str1.title()
    print(titleStr)                 # Hello, World
    
  • 字符串的对齐方式

    # 对齐方式方法,第一个参数指定宽度,第2个参数指定填充符,第2个参数可选,默认为空格,如果宽度小于实际宽度,则返回原字符串
    str1 = "Hello, Python"
    
    # 1. center(): 居中对齐
    print(str1.center(20, "#"))             # ###Hello, Python####
    
    # 2. ljust(): 左对齐
    print(str1.ljust(20, "#"))              # Hello, Python#######
    
    # 3. rjust(): 右对齐
    print(str1.rjust(20, "#"))              # #######Hello, Python
    
    # 如果指定宽度小于实际宽度,则返回原字符串
    print(str1.rjust(10, "#"))              # Hello, Python
    
    # zfill(): 右对齐,左边用 0 填充,只接收一个参数,用于指定字符串的宽度,如果宽度小于等于字符串的长度,返回字符串本身
    print(str1.zfill(20))                   # 0000000Hello, Python
    
    # 数字有点特殊
    print("12345".zfill(10))        # 0000012345
    print("-12345".zfill(10))       # -000012345  , 从 - (负号)后面开始填充
    
  • 字符串的劈分

    # 1. split()
    # 从字符串的左边开始劈分,默认的劈分字符是空格,返回的值是一个列表
    # 通过参数 sep 指定劈分字符串的劈分符
    # 通过参数 maxsplit 指定劈分字符串时的最大劈分次数,在经过最大劈分次数后,剩余的子串会单独作为一份
    str1 = "Hello world Python"
    print(str1.split())                         # ['Hello', 'world', 'Python']
    
    str2 = "Hello|world|Python"
    print(str2.split(sep='|'))                  # ['Hello', 'world', 'Python']
    
    print(str2.split(sep='|', maxsplit=1))      # ['Hello', 'world|Python']
    
    # 2. rsplit(): 从右边开始劈分,参数和作用同上
    print(str2.rsplit(sep='|', maxsplit=1))     # ['Hello|world', 'Python']
    
  • 字符串判断的相关操作

    # 1. isidentifier(): 判断指定的字符串是否是合法的标识符
    print("abc%".isidentifier())        # False
    
    # 2. isspace(): 判断指定的字符串是否 全部 由 空白字符组成(回车、换行、水平制表符)
    print("\t".isspace())               # True
    
    # 3. isalpha(): 判断指定的字符串是否 全部 由 字母 组成
    print("abc1".isalpha())             # False
    
    # 4. isdecimal(): 判断指定的字符串是否 全部 由 十进制 的数字组成
    print("1234".isdecimal())           # True
    
    # 5. isnumeric(): 判断指定的字符串是否 全部 由 数字 组成
    print("123四".isnumeric())           # True
    
    # 6. isalnum(): 判断指定的字符串是否 全部 由 字母和数字 组成
    print("abc四".isalnum())             # True
    
  • 字符串的替换和合并

    # 1. replace(): 第1个参数 -> 被替换的子串,第2个参数 -> 替换子串的字符串, 第3个参数 -> 最大替换次数。该方法返回替换后的字符串
    str1 = "Hello Python Python Python"
    newStr = str1.replace("Python", "Java", 2)
    print(newStr)           # Hello Java Java Python
    
    # 2. join(): 将列表或元组中的字符串合并成一个字符串
    strs = ["hello", "Python", "Hello", "Java"]
    joinStr = " ".join(strs)        # 用 “ ” 将列表中的元素拼接到一起
    print(joinStr)                  # hello Python Hello Java
    
    strTuple = ("C", "Python", "Java")
    print(" | ".join(strTuple))       # C | Python | Java
    
    str = "Python"
    print("*".join(str))            # P*y*t*h*o*n, 字符串也是列表
    
  • 字符串的比较

    # 运算符:> , < , >= , <= , == , !=
    
    # 比较规则:首先比较两个字符串的第一个字符,如果相等,则继续比较下一个字符,依次比较下去。
    #         直到两个字符串的字符不相等,其比较结果就是两个字符串的比较结果。
    #         两个字符串中所有后续字符将不再比较
    
    # 比较原理:两个字符比较时,比较的是其 ordinal value (原始值),调用内置函数 ord() ,可以得到指定字符的 ordinal value。
    # 与内置函数 ord() 对应的是内置函数 chr() ,调用内置函数 chr() 时指定 ordinal value可以得到其对应的字符
    
    print("alpha" > "alp")          # True
    print("alpha" > "banana")       # False
    print(ord("a"), ord("b"))       # 97 98  因为第一个字符 a 的 ordinal value 比 b 小,所以 "alpha" < "banana"
    print(chr(97), chr(98))         # a b
    
    # == 和 is 的区别: == 比较的是 value,is 比较的是 id
    a = b = "Python"
    c = "".join("Python")
    
    print(a == b)           # True
    print(a is b)           # True
    print(a == c)           # True
    print(a is c)           # False
    
  • 字符串的切片

    # 字符串是不可变类型,所以不具备增删改等操作,而且,切片操作将产生新的对象
    s = "Hello, Python"
    s1 = s[:5]              # 由于没有指定起始位置,所以默认从 0 开始
    s2 = s[6:]              # 由于没有指定结束位置,所以切到字符串的最后一个元素
    s3 = " #"
    print(s1 + s3 + s2)     # Hello # Python
    
    # s[start: end: step]
    print(s[1: 5: 1])       # ello , 从1开始,截取到5 (不包含5),步长为1
    print(s[::2])           # Hlo yhn , 没指定起始位置和结束位置,按默认的从0开始截取到最后一个元素,步长为2
    print(s[::-1])          # nohtyP ,olleH, 默认从字符串最后一个元素开始,到字符串的第一个元素结束,因为步长为负数
    print(s[-6::1])         # Python , 从索引-6开始,到字符串的最后一个元素结束,步长为1,所以,步长决定截取的方向,而不是由索引决定
    
  • 字符串的格式化

    # 1. % 占位符   %s -> 字符串, %d 或 %i -> 整数, %f -> 浮点数
    name = "Tomas"
    age = 20
    print("我叫%s,今年%d岁" % (name, age))
    
    # 指定宽度
    print("%10d" % 99)              #         99, 10表示宽度,在99的前面填充了8个空格
    # 指定精度
    print("%f" % 3.1415926)         # 3.141593 , 默认小数点后6位
    print("%.10f" % 3.1415926)      # 3.1415926000
    print("%.3f" % 3.1415926)       # 3.142, .3 表示小数点后3位,会四舍五入
    # 同时指定宽度和精度
    print("%10.3f" % 3.1415926)     #      3.142, 总共10宽度,并保留小数点后3位
    
    
    # 2. {} 占位符
    print("我叫{0},今年{1}岁".format(name, age))         # {} 里面的数字代表是format() 中的第几个变量,从0开始
    
    # 另一种写法:f-string
    print(f"我叫{name},今年{age}岁")
    
    # 指定宽度
    print("{:10}".format(99))               #         99, 总共10宽度
    # 指定精度
    print("{0:.3}".format(3.1415926))       # 3.14, .3 表示一共3位数,注意,是一共,会四舍五入
    print("{:.3f}".format(3.1415926))       # 3.142, .3f 表示是3位小数,会四舍五入
    # 同时指定宽度和精度
    print("{:10.3f}".format(3.1415926))     #      3.142
    
  • 字符串的编码和解码

    # 1. 编码:将字符串转换成二进制数据(bytes)
    s = "你好啊"
    print(s.encode("utf-8"))
    print(s.encode(encoding="utf-8"))   # utf-8 编辑格式,一个中文占三个字节
    print(s.encode("gbk"))
    print(s.encode(encoding="gbk"))     # gbk 编辑格式,一个中文占两个字节
    
    # 2. 解码:将bytes类型的数据转换成字符串类型
    b = s.encode("utf-8")
    print(b.decode(encoding="utf-8"))   # 你好啊
    # 不能将一种格式的编码 解码成另一种格式的
    print(b.encode(encoding="gbk"))     # AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?
    

字符串总结

image-20221028140137603

函数

  • 函数的创建

    # 创建格式
    # def functionName(参数列表):
    #     functionBody
    #     [ return result ] 这部分可省略
    
    # 创建函数
    def sum(x, y):
        result = x + y
        return result
    
    # 调用函数: functionName(参数)
    result = sum(10, 20)
    print(result)           # 30
    
  • 函数的参数传递

    def sum(a, b):
        return a + b
    
    # 1. 位置实参:根据形参的对应位置进行实参传递
    print(sum(10, 20))          # 30, 这里直接给的实参,那么实参会按顺序赋值给对应位置的形参,一个萝卜一个坑
    
    # 2. 关键字实参:根据形参名称进行实参传递
    print(sum(b = 10, a = 20))  # 30, 直接指明了哪个形参的值是多少,点名道姓
    
  • 函数的返回值

    # 1. 如果函数没有返回值,即函数执行完毕后,不需要给调用者返回数据,return 可以省略不写
    def sayHello():
        print("Hello")
    
    sayHello()
    
    # 2. 函数的返回值有 1 个,直接返回原类型
    def appendList(args):
        args.append(99)
        return args
    
    args = [10, 12, 11, 13, 19, 89]
    print(type(appendList(args)))     # <class 'list'>
    
    # 3. 函数的返回值有 多个,返回的结果是 元组
    def oddOrEven(args):
        odd = []
        even = []
        for i in args:
            if i % 2:
                odd.append(i)
            else:
                even.append(i)
        return odd, even
    
    print(oddOrEven(args))          # ([11, 13, 19, 89, 99], [10, 12])
    
  • 函数定义默认值参数

    # 函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参
    def fun(a, b = 10):
        return a + b
    
    print(fun(20))          # 30, 只给了一个实参,所以 形参b 取默认值
    
    print(fun(20, 50))      # 70, 给了两个实参,所以 形参b 使用传递的实参 50
    
  • 个数可变的形参

    # 个数可变的位置参数
    #   1. 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数
    #   2. 使用 * 定义个数可变的位置形参
    #   3. 结果为一个 元组
    def fun1(*args):
        print(args)
    
    fun1(10, 20, 30)        # (10, 20, 30)
    
    # 个数可变的关键字形参
    #   1. 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的关键字形参
    #   2. 使用 ** 定义个数可变的关键字形参
    #   3. 结果为一个 字典
    def fun2(**args):
        print(args)
    
    fun2(a = 1, name = "zhangsan", age = 20)        # {'a': 1, 'name': 'zhangsan', 'age': 20}
    
    # 个数可变的位置形参,只能有 1 个
    # def fun3(*args1, *args2):       # SyntaxError: invalid syntax
    #     pass
    
    # 个数可变的关键字形参,只能有 1 个
    # def fun4(**args1, **args2): # SyntaxError: invalid syntax
    #     pass
    
    # 如果既有个数可变的 关键字形参,又有个数可变的 位置形参,要求:个数可变的位置形参,放在个数可变的关键字形参之前
    # def fun5(**args1, *args2):      # SyntaxError: invalid syntax
    #     pass
    
    # 个人理解,* 和 ** 就像是个打包和解包的符号,将参数个数可变的参数都打包成一个元组 或 字典
    # 也可以通过 * 和 ** 将元组、列表、字典解包
    def fun(a, b, c):
        print(a, b, c)
    
    fun(10, 20, 30)         # 10 20 30
    # 通过 * 将元组 或 列表解包
    tuple1 = (11, 12, 13)
    list1 = [21, 22, 23]
    fun(*tuple1)            # 11 12 13
    fun(*list1)             # 21 22 23
    
    # 通过 ** 将 字典 解包
    dict1 = {'a': 1, 'b': 2, 'c': 3}
    fun(**dict1)            # 1 2 3
    # 此时,字典中的键值对必须符合关键字实参,也就是说,键必须和函数的形参一样
    dict2 = {'a': 1, 'b': 2, 'name': 3}
    fun(**dict2)            # TypeError: fun() got an unexpected keyword argument 'name'
    
  • 变量的作用域

    # 局部变量
    def say():
        args = "Hello"
        print(args)
    
    # args 在函数内定义的,是局部变量
    # print(args)         # NameError: name 'args' is not defined
    
    # 可以通过关键字 global 将局部变量变为全局变量
    def say2():
        global str
        str = "Python"
        print(str)
    
    # 不过要先调用该函数,才能全局使用该变量
    say2()
    print("Hello, " + str)      # Hello, Python
    
    # 全局变量: 函数外定义的变量
    name = "zhangsan"
    def printStr():
        print(name)
    
    printStr()          # zhangsan
    
  • 递归函数

    # 递归函数应该由 递归条件 和 终止条件 组成
    # 用递归计算阶乘
    def factorial(num):
        if num == 1:
            return 1
        return num * factorial(num -1)
    
    print(factorial(6))
    
    # 用递归算斐波那契数
    # 斐波那契数:前两个斐波那契数之和
    def Fibonacci(num):
        if num == 0:
            return 0
        elif num == 1:
            return 1
        return Fibonacci(num - 1) + Fibonacci(num - 2)
    # 1 1 2 3 5 8 13 21 34
    print(Fibonacci(10))
    

异常

  • try - except 结构

    # 一个交互式计算两个整数之和的程序
    # 如果用户不小心输入第二个整数时输入0,0是不能作为除数的,会报 ZeroDivisionError 错误
    # 因此,可以使用 try - except 对异常进行捕获,输出让用户理解的错误信息
    try:
        n1 = int(input("请输入一个整数: "))
        n2 = int(input("请输入另一个整数: "))
        result = n1 / n2
        print("这两个整数的和为: ", result)
    except ZeroDivisionError:
        print("不好意思,除数不能为0")
    
  • try - except - except 多 except结构

    # 使用 try - except 解决输入除数为0的情况,不过,当用户输入的不是数值类型时,会报 ValueError 错误
    # 可以使用多个 except 捕获不同的异常
    # 多个 except 结构:捕获异常的顺序按照先子类后父类的顺序,为了避免遗漏可能出现的异常,可以在最后增加 BaseException
    try:
        n1 = int(input("请输入一个整数: "))
        n2 = int(input("请输入另一个整数: "))
        result = n1 / n2
        print("这两个整数的和为: ", result)
    except ZeroDivisionError:
        print("不好意思,除数不能为0")
    except ValueError:
        print("不好意思,请输入整数")
    except BaseException:
        print("未知错误,请通知管理员")
    
  • try - except - else 结构

    # try - except - else 结构:如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块
    try:
        n1 = int(input("请输入一个整数: "))
        n2 = int(input("请输入另一个整数: "))
        result = n1 / n2
        print("这两个整数的和为: ", result)
    except ZeroDivisionError:
        print("不好意思,除数不能为0")
    except ValueError:
        print("不好意思,请输入整数")
    except BaseException:
        print("未知错误,请通知管理员")
    else:
        print("这两个整数的和为: ", result)
    
  • try - except - else - finally 结构

    # try - except - else - finally 结构:finally块无论是否发生异常,都会执行,常用来释放try块中申请的资源
    try:
        n1 = int(input("请输入一个整数: "))
        n2 = int(input("请输入另一个整数: "))
        result = n1 / n2
    except ZeroDivisionError:
        print("不好意思,除数不能为0")
    except ValueError:
        print("不好意思,请输入整数")
    except BaseException:
        print("未知错误,请通知管理员")
    else:
        print("这两个整数的和为: ", result)
    finally:
        print("感谢您的使用")
    
  • 获取异常信息

    try:
        n1 = int(input("请输入一个整数: "))
        n2 = int(input("请输入另一个整数: "))
        result = n1 / n2
    except ZeroDivisionError as e:
        print(e)                        # division by zero
        print("不好意思,除数不能为0")
    
  • 常见的异常类型

  • traceback 模块

    # 使用 traceback 模块打印异常信息,常用于保存日志信息
    import traceback
    try:
        print("==================================")
        print(1 / 0)
    except:
        traceback.print_exc()
    

类与对象

  • 类的创建 和 对象的创建

    # 类的创建
    class Student:
        # 类属性
        address = "湖南"
    
        # 初始化方法 (构造函数)
        def __init__(self, name, age):
            self.name = name        # self.name 称为实例属性
            self.age = age
    
        # 实例方法
        def eat(self):
            print(self.name, "正在吃饭。。。")
    
        # 静态方法
        # 使用 @staticmethod 注解,形参中不需要添加 self
        @staticmethod
        def static(name):
            print("这是一个静态方法", name)
    
        # 类方法
        # 使用 @classmethod 注解,形参中必须添加 cls ,这是 class的缩写
        @classmethod
        def cm(cls):
            print("这是一个类方法")
            
    # 对象的创建
    student1 = Student("zhangsan", 20)
    
    # 对象调用方法的两种方式
    student1.eat()
    Student.eat(student1)
    
  • 类属性、类方法、类静态方法

    # 类属性:类中且方法外的变量称为类属性,被该类的所有对象共享
    student2 = Student("lisi", 21)
    print(student1.address, student2.address)       # 湖南 湖南
    
    # 类方法:使用 @classmethod 修饰的方法,使用类名直接访问的方法
    Student.cm()        # 这是一个类方法
    
    # 静态方法:使用 @staticmethod 修饰的方法,使用类名直接访问的方法,没有默认形参,类方法有默认形参 cls
    Student.static(student1.name)       # 这是一个静态方法 zhangsan
    
  • 对象的动态绑定

    # 对象动态绑定属性和方法
    # 1. 动态绑定属性
    student1.gender = 'male'
    print(student1.gender)          # male
    # 只对添加了属性的对象生效,并不是给类添加了属性
    # print(student2.gender)          # AttributeError: 'Student' object has no attribute 'gender'
    
    # 2. 动态绑定方法
    def show(name):
        print(name, "说:这是一个动态绑定的方法")
    
    # 动态绑定方法时,不用加 ()
    student1.show = show
    student1.show(student1.name)    # zhangsan 说:这是一个动态绑定的方法
    
  • 面向对象三大特性

    • 封装

      # 封装
      # 1. 将属性和方法包装在类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。
      # 这样,无需关系方法内部的具体实现细节,从而隔离了复杂度
      # 2. 在Python中没有专门的修饰符用于属性的私有,如果不希望在类对象外部被访问,前面使用两个 _ (下划线)
      
      class Student:
          def __init__(self, name, age):
              self.name = name
              self.__age = age        # age 属性前面添加两个 _ (下划线),将属性设置为私有
      
          def show(self):
              print("我叫{},今年{}岁了".format(self.name, self.__age))  # age 属性在类内可以访问
      
      stu1 = Student("zhangsan", 20)
      # 无法通过 objectName.attribute 的形式来访问私有属性
      # print(stu1.__age)           # AttributeError: 'Student' object has no attribute '__age'
      stu1.show()
      
      # 不过,Python 中并没有真正意义上的私有属性
      # 内置函数 dir(object): 可以获取对象的所有属性,包括 __ 开头的属性。
      print(dir(stu1))            # 从中发现,__age属性的名称为_Student__age
      
      print(stu1._Student__age)   # 20, 可以通过 stu1._Student__age 访问私有属性 __age
      
      # 类中声明的私有属性可以通过 _className__私有属性 的方式访问。
      # 所以,Python中没有私有属性,把 __ 开头的属性作为私有属性的含义只是一种约定俗成,当程序员发现属性为 __ 开头,就把它当成私有属性就好了
      
    • 继承

      # 继承:提高代码的复用性
      # 如果一个类没有继承任何类,则默认继承object
      # class Father(object):
      class Father():
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def show(self):
              print("我叫{},今年{}岁".format(self.name, self.age))
      
      class Mother():
          def __init__(self, gender):
              self.gender = gender
      
          def play(self, hobbit):
              print("我喜欢{}".format(hobbit))
      
      # 继承的语法格式:
      # class 子类(父类):
      class Son(Father):
          def __init__(self, name, age, hobbits):
              # 定义子类时,必须在其构造函数中调用父类的构造函数。没规定父类构造函数必须是第一行
              super().__init__(name, age)
              self.hobbits = hobbits
      
          # 方法重写
          def show(self):
              # 可使用 super().父类的方法 来使用重写前的方法
              super().show()
              print("我是子类,我重写了父类")
      
      son1 = Son("cxk", 20, "唱,跳,rap,篮球")
      # 子类继承了父类的方法
      son1.show()
      # 方法重写后,调用show()方法
      son1.show()
      
      # Python支持多继承
      class Child(Father, Mother):
          def __init__(self, name, age, gender, hobbit):
              # 调用父类的初始化方法,需要传入 self
              Father.__init__(self, name, age)
              Mother.__init__(self, gender)
              self.hobbit = hobbit
      
      child1 = Child("cxk", 20, "male", "唱,跳,rap, 篮球")
      child1.show()
      child1.play(child1.hobbit)
      
    • 多态

      class Animal():
          """动物类"""
          def __init__(self):
              pass
      
          def eat(self):
              print("正在吃东西...")
      
      class Cat(Animal):
          """猫咪类,继承动物类"""
          def __init__(self):
              pass
      
          def eat(self):
              print("猫咪正在吃鱼...")
      
      class Dog(Animal):
          """狗狗类,继承动物类"""
          def __init__(self):
              pass
      
          def eat(self):
              print("狗狗正在吃骨头...")
      
      class Person():
          """人类"""
          def __init__(self):
              pass
      
          def eat(self):
              print("人正在吃饭...")
      
      def fun(obj):
          """执行obj对象的eat()方法"""
          obj.eat()
      
      # 多态:即 ”具有多种形态“,指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,
      # 在运行过程中根据变量所引用的对象的类型,动态决定调用哪个对象的方法
      fun(Animal())           # 正在吃东西...
      fun(Cat())              # 猫咪正在吃鱼...
      fun(Dog())              # 狗狗正在吃骨头...
      
      # 注意
      # 静态语言和动态语言关于多态的区别
      # 静态语言(如Java)实现多态的三个必要条件
      #     1. 继承
      #     2. 方法重写
      #     3. 父类引用指向子类对象
      
      # 动态语言(如Python)的多态崇尚 ”鸭子类型“ :当看到一只鸟走起来像鸭子、游泳起来像鸭子,那么这只鸟就可以被称为鸭子。
      # 在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为
      # Person类并不是Animal类的子类,但Person类也有 eat() 方法,因此也符合动态语言的多态
      fun(Person())           # 人正在吃饭...
      
  • object 类

    # object类是所有类的父类,因此,所有类都有object类的属性和方法
    # 1. 内置函数 dir() : 可以查看指定对象所有属性
    class Student:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        """重写__str__()方法"""
        def __str__(self):
            return "我的名字是{},今年{}岁".format(self.name, self.age)
    
    stu = Student("zhangsan", 20)
    print(dir(stu))
    
    # 2. object有一个 __str__() 方法,用于返回一个对于 ”对象的描述“,类似于Java中的toString()方法
    # 对应于内置函数 str(),经常用于print()方法,帮助查看对象的信息,所以经常会对__str__() 进行重写
    
    # 未重写 __str__() 方法时,打印信息为 对象的类型 和 对象的地址
    print(stu)                  # <__main__.Student object at 0x00000207569290C0>,直接print(对象),默认调用对象的__str__() 方法
    
    # 重写 __str__() 方法后,打印重写后的 return 返回的信息
    print(stu)                  # 我的名字是zhangsan,今年20岁
    
  • 特殊属性

    class A:
        def __init__(self):
            pass
    
    class B:
        def __init__(self):
            pass
    
    class C(A, B):
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    # 特殊属性
    c = C("zhangsan", 20)
    print(c.__dict__)           # 实例对象的属性字典
    print(C.__dict__)           # 类的属性字典
    
    print(c.__class__)          # 对象所属的类
    
    print(C.__bases__)          # C 类的父类类型的元组
    print(C.__base__)           # C 类的基类,基类根据 类声明中 class C(A, B): 括号内哪个类在前面,哪个类就是基类
    
    print(C.__mro__)            # 类的层次结构,也就是类的继承结构
    
    print(A.__subclasses__())   # 类的子类列表
    
  • 特殊方法

    # 1. __add__() 方法
    a = 10
    b = 20
    c = a + b
    print(c)
    
    # 两个整数之所以可以通过 ” + “ 作相加操作,是因为整数有__add__()方法
    d = a.__add__(b)            # 等同于 a + b
    print(d)
    
    class Student:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        """重写__add__()方法"""
        def __add__(self, other):
            return self.age + other.age
    
        """重写__len__()方法"""
        def __len__(self):
            return len(self.name)
    
    stu1 = Student("zhangsan", 20)
    stu2 = Student("lisi", 21)
    
    # 对象之间无法使用 "+" 相加操作
    stu3 = stu1 + stu2          # TypeError: unsupported operand type(s) for +: 'Student' and 'Student'
    # 可以通过重写 __add__() 方法,使自定义的对象具有 "+"功能
    stu4 = stu1 + stu2
    stu5 = stu1.__add__(stu2)
    print(stu4, stu5)           # 41 41
    
    # 2. __len__() 方法
    # 列表可以使用内置函数 len() 来获取列表的长度, 而Student对象却会报错
    list1 = [1, 2, 3, 4, 6]
    print(len(list1))
    # print(len(stu1))            # TypeError: object of type 'Student' has no len()
    
    # 这是因为列表重写了__len__()方法
    print(list1.__len__())
    
    # 通过重写__len__()方法,让内置函数len()的参数可以是自定义对象的类型
    print(len(stu1))            # 8
    print(len(stu2))            # 4
    
    # 特殊方法 __new__() 和 __init__()
    class Person():
        def __new__(cls, *args, **kwargs):
            print("__new__方法被调用,cls的id值为: {}".format(id(cls)))
            obj = super().__new__(cls)
            print("创建的对象的id值为: {}".format(id(obj)))
            return obj
    
        def __init__(self, name, age):
            print("__init__方法被调用,self的id值为: {}".format(id(self)))
            self.name = name
            self.age = age
    
    print("object 类的id值为: {}".format(id(object)))
    print("Person 类的id值为: {}".format(id(Person)))
    
    # 创建Person类的实例对象
    p1 = Person("zhangsan", 20)
    print("p1 这个Person类的实例对象的id值为: {}".format(id(p1)))
    
    # 由上面的代码的输出内容以及debug可知,
    # 执行 p1 = Person("zhangsan", 20) 时,
    # 先调用Person类的__new__()方法,其中参数cls = Person类,args = ["zhangsan", 20],所以cls的id值和Person类的id值相同
    # 然后调用父类object的__new__()方法,传入cls,返回一个对象,
    # 接着,会调用__init__()方法,将刚创建的obj和agrs中的值传入,所以 self 和 obj 的id值一样。
    # __init__()方法执行完之后,会将生成的对象赋值给p1
    
  • 对象的拷贝

    # 变量的赋值
    # 只是形成两个变量,实际上还是指向同一个对象
    a = 100
    b = a
    print(id(a), id(b))
    
    class CPU():
        def __init__(self):
            pass
    
    class Disk():
        def __init__(self):
            pass
    
    class Computer():
        def __init__(self, cpu, disk):
            self.cpu = cpu
            self.disk = disk
    
    # 浅拷贝
    # Python拷贝一般是浅拷贝,拷贝时,对象包含的子对象的内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象
    cpu = CPU()
    disk = Disk()
    computer = Computer(cpu, disk)
    
    # 对象的拷贝需要导入copy模块
    import copy
    computer2 = copy.copy(computer)
    # 打印输出的id值,computer 和 computer2的id不同,但两对象的cpu属性和disk属性的id值相同
    # 浅拷贝只拷贝了一份引用,并没有拷贝一份子对象
    print(id(computer), id(computer.cpu), id(computer.disk))
    print(id(computer2), id(computer2.cpu), id(computer2.disk))
    
    # 深拷贝
    # 使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
    computer3 = copy.deepcopy(computer)
    print(id(computer), id(computer.cpu), id(computer.disk))
    print(id(computer3), id(computer3.cpu), id(computer3.disk))
    

模块

  • 导入模块

    # import 模块名 [as 别名]
    # 导入的是整个模块
    import math as m
    
    print(m.pi)
    print(m.pow(2, 2))
    
    # from 模块名 import 函数/变量/类
    # 导入的是模块的部分,导入多个用 , 隔开
    # 未导入的内容无法访问
    from math import pow
    
    print(pow(2, 10))
    print(pi)       # NameError: name 'pi' is not defined
    
  • 主程序

    # 主程序
    # 在每个模块的定义中,都包括一个记录模块名称的变量 __name__ ,程序可以检查该变量,以确定它们在哪个模块中执行。
    # 如果一个模块不是被导入到其他程序中执行,那么它可能在解释器的顶级模块中执行
    # 顶级模块的 __name__ 变量的值为 __main__
    
    import math
    
    def perimeter(r):
        """计算圆的周长"""
        return 2 * r * math.pi
    
    # 这条语句相当于Java中的main方法
    if __name__ == '__main__':
        print(perimeter(4).__floor__())
    
  • 常用的模块

    image-20221030232644935

  • 第三方模块的安装和使用

    • 安装

      • 终端中使用命令:pip install 模块名

        image-20221030233258216

    • 使用

      import schedule
      import time
      
      def job():
          print("哈哈哈哈")
      
      # schedule 是一个定时任务模块,可用于定时发送邮件等业务
      schedule.every(3).seconds.do(job)       # 每三秒执行一次 job() 方法
      while True:
          schedule.run_pending()
          time.sleep(1)               # 停顿 1 秒
      

  • Python中的包

    • 包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下
    • 作用:
      • 代码规范
      • 避免模块名称冲突
  • 包和目录的区别

    • 包含 " __ init __.py"文件的目录称为包
    • 目录中通常不包含 "__ init __.py"文件
  • 包的导入

    # import 方式导入
    # 使用 import 方式进行导入时,只能跟 包名或模块名
    # import package1.moduleA
    import package1.moduleA as A
    
    # 这样使用value值需要 包名.模块名.变量
    # 可以在导入包或模块时,给包或模块一个别名
    # print(package1.moduleA.value)
    print(A.value)
    
    # from...import... 方式导入
    # 使用 from... import... 方式导入时,可以导入包、模块、函数、变量
    from package1.moduleB import value
    print(value)
    

文件

  • 编码格式

    • Python的解释器使用的是 Unicode (内存)

    • .py 文件在磁盘上使用的是 UTF-8 (外存)

    • 在 .py 文件 中,可以通过在第一行添加 # encoding = “” 来指定编码格式

      # encoding= gbk
      """
      @title: 
      @description: 文件的编码格式
      @date: 2022/11/3-20:20
      """
      

      image-20221103202151124

  • 内置函数open()

    # 内置函数open()创建文件对象
    # 语法规则:file = open(filename [, mode, encoding])
    # filename : 要创建或打开的文件名称
    # mode : 打开模式,默认是只读
    # encoding : 默认文本文件中字符的编码格式为gbk
    # file : 被创建的文件对象
    file = open("test.txt", "r", encoding="utf-8")      # 由于 test.txt 文件默认编码格式是gbk,不添加encoding = "utf-8" 会报错
    print(file.readlines())     # ['你好,世界\n', 'Python'] , 返回的是一个列表
    file.close()
    
  • 文件的打开模式

    • 文件的类型:

      • 按文件中数据的组织形式,文件分为以下两大类
        1. 文本文件:存储的是普通的 “字符” 文本,默认为 Unicode 字符集,可以使用记事本程序打开
        2. 二进制文件:把数据内容用 “字节” 进行存储,无法用记事本打开,必须使用专用的软件打开,举例:mp3音频文件,jpg图片,.doc 文档等
    • 打开模式

      image-20221103210315262

    # w 模式
    file_W = open("test.txt", "w", encoding="utf-8")
    file_W.write("Java")
    file_W.close()
    
    # a 模式
    file_A = open("test.txt", "a", encoding="utf-8")
    file_A.write(" Python")
    file_A.close()
    
    # b 模式,b 模式不能单独使用,需要和其他模式一起使用,如 rb、wb,常用于二进制文件的复制
    src_file = open("LaPluma.png", "rb")
    target_file = open("CopyLaPluma.png", "wb")
    
    target_file.write(src_file.read())
    target_file.close()
    src_file.close()
    
  • 文件对象的常用方法

    image-20221103212107750

  • with 语句 (上下文管理器)

    • with 语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件的正确关闭,以此来达到释放资源的目的

    • 原理

      image-20221103213001611

    • 代码演示

      # 语法格式:
      # with  上下文表达式  as  上下文管理器的引用:
      #   with 语句体
      
      # 上下文表达式:该表达式的结果为一个 上下文管理器,同时会自动调用该上下文管理器的 __enter__()方法,并将返回值赋值给 上下文管理器引用
      # 上下文管理器:一个类,实现了 __enter__() 方法和 __exit__() 方法,则这个类遵守了 上下文管理协议,那么这个类就是一个上下文管理器
      # 当 with 块执行完后,会自动调用 上下文管理器的 __exit__() 方法
      
      class MyContentManager(object):
          def __enter__(self):
              print("enter方法被调用了")
              # 这里要返回对象,不然会报错:AttributeError: 'NoneType' object has no attribute 'show'
              # 因为执行到上下文表达式之后,要将该上下文管理器的引用赋值给 as 后的引用
              return self        
      
          def __exit__(self, exc_type, exc_val, exc_tb):      # 除self 参数外,还必须要这三个参数
              print("exit方法被调用了")
      
          def show(self):
              print("show方法被调用了")
      
      with MyContentManager() as file:    # 这句相当于是:file = MyContentManager()
          file.show()
      
      # 用 with块实现图片的复制
      with open("LaPluma.png", "rb") as src_file:
          with open("CopyLaPluma2.png", "wb") as target_file:
              target_file.write(src_file.read())
      

OS 模块

  • os 模块是Python内置的与操作系统功能和文件系统相关的模块。

  • 该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上允许,得到的结果可能不一样

  • os 模块 与 os.path 模块用于对目录或文件进行操作

  • os 模块的常用函数

    image-20221103221642927

  • os.path 模块 操作目录相关的函数

    image-20221103221809598

coding = “utf-8” 会报错
print(file.readlines()) # [‘你好,世界\n’, ‘Python’] , 返回的是一个列表
file.close()




* 文件的打开模式

* 文件的类型:

  * 按文件中数据的组织形式,文件分为以下两大类
    1. **文本文件**:存储的是普通的 “字符” 文本,默认为 Unicode 字符集,可以使用记事本程序打开
    2. **二进制文件**:把数据内容用 “字节” 进行存储,无法用记事本打开,必须使用专用的软件打开,举例:mp3音频文件,jpg图片,.doc 文档等

* 打开模式

  [外链图片转存中...(img-pmBgx7q0-1679489217514)]

~~~python
# w 模式
file_W = open("test.txt", "w", encoding="utf-8")
file_W.write("Java")
file_W.close()

# a 模式
file_A = open("test.txt", "a", encoding="utf-8")
file_A.write(" Python")
file_A.close()

# b 模式,b 模式不能单独使用,需要和其他模式一起使用,如 rb、wb,常用于二进制文件的复制
src_file = open("LaPluma.png", "rb")
target_file = open("CopyLaPluma.png", "wb")

target_file.write(src_file.read())
target_file.close()
src_file.close()
  • 文件对象的常用方法

    [外链图片转存中…(img-4pIiYwGE-1679489217515)]

  • with 语句 (上下文管理器)

    • with 语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件的正确关闭,以此来达到释放资源的目的

    • 原理

      [外链图片转存中…(img-GqI2ikmJ-1679489217516)]

    • 代码演示

      # 语法格式:
      # with  上下文表达式  as  上下文管理器的引用:
      #   with 语句体
      
      # 上下文表达式:该表达式的结果为一个 上下文管理器,同时会自动调用该上下文管理器的 __enter__()方法,并将返回值赋值给 上下文管理器引用
      # 上下文管理器:一个类,实现了 __enter__() 方法和 __exit__() 方法,则这个类遵守了 上下文管理协议,那么这个类就是一个上下文管理器
      # 当 with 块执行完后,会自动调用 上下文管理器的 __exit__() 方法
      
      class MyContentManager(object):
          def __enter__(self):
              print("enter方法被调用了")
              # 这里要返回对象,不然会报错:AttributeError: 'NoneType' object has no attribute 'show'
              # 因为执行到上下文表达式之后,要将该上下文管理器的引用赋值给 as 后的引用
              return self        
      
          def __exit__(self, exc_type, exc_val, exc_tb):      # 除self 参数外,还必须要这三个参数
              print("exit方法被调用了")
      
          def show(self):
              print("show方法被调用了")
      
      with MyContentManager() as file:    # 这句相当于是:file = MyContentManager()
          file.show()
      
      # 用 with块实现图片的复制
      with open("LaPluma.png", "rb") as src_file:
          with open("CopyLaPluma2.png", "wb") as target_file:
              target_file.write(src_file.read())
      

OS 模块

  • os 模块是Python内置的与操作系统功能和文件系统相关的模块。

  • 该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上允许,得到的结果可能不一样

  • os 模块 与 os.path 模块用于对目录或文件进行操作

  • os 模块的常用函数

    [外链图片转存中…(img-dmo2JTdH-1679489217516)]

  • os.path 模块 操作目录相关的函数

    [外链图片转存中…(img-WMo28VjT-1679489217517)]

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值