python基础知识

编程语言

编程语言都是高级计算机语言,设计的目的为乐程序员的使用,而计算机能识别的是机器语言,也被称为低级计算机语言

如果将高级语言翻译成计算机可识别的机器语言,有两种方式

  • 编译器
  • 解释器

编译型语言

  • 使用编译器将自身转化为机器语言
  • 代表语言 c语言 c++
  • 一次性将所有的源代码转化成为二进制指令,形成一个可执行文件win.exe
  • 一次编译无限次运行
  • 下载的是可执行文件,源代码被作者保留,闭源

解释型语言

  • 使用解释器将自身转化为机器语言
  • 代表原因python php
  • 每次执行程序,都要重新解释源代码,所以效率低于编译型语言
  • 下载的时候源代码,所以一般解释型语言是开源的

Python基础知识

编码规范

编码规范:python使用缩进区分代码的包含关系,缩进一般代指tab键,4个空格

标识符的命名规范

  • 由数字、字母、下划线组成,数字不能开头,【字母:不单指英文字母,所有国家的语言都被称为字母】

  • 不能使用python中的关键字

    • import keyword 
      
      print(keyword.kwlist)
      
      ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
      
      
  • 以下划线开头是具有特殊含义的,面向对象部门会涉及 _abc

  • 能够提示出来的单词不使用

  • 见名知意

  • 多个单词使用下划线隔开

定义变量

  • 定义单个变量

  • 变量名 = 值

  • 定义多个变量

    • 多个变量值相等

      • 变量名1 = 变量名2 = 值
      a = b = 1
      
    • 多个变量值不等

      • 变量名1,变量名2 = 值1,值2
      a,b = 1,2    # a = 1, b=2
      

注释的使用

注释的内容不会参与逻辑运算,只是展示代码的功能

  • 单行注释

    • # 内容
    • ctrl + /
  • 多行注释

    • ''' 注释内容 '''

数据类型

  • 根据数据的特征,进行分类,对应不同的数据类型
  • 查看数据的数据类型 type(数据)
整型 – int
  • 数学中的整数
a = 10
print(a, type(a))  # 10<class 'int'>
浮点型 – float
  • 数学中的小数
b = 10.2
print(b, type(b))  # 10.2 <class 'float'>
布尔类型 – bool
  • 只有两个值,用来描述逻辑是否成立
  • True False
c = True
print(c, type(c))  # True<class 'bool'>
字符串类型 – str
  • 存储文本数据 ,需要成对的单引号或者双引号包含
d = '哈哈哈哈'
print(d, type(d))  # 哈哈哈哈<class 'str'>

e = '10'
print(e, type(e))  # 10<class 'str'>

f = 'True'
print(f, type(f))  # True<class 'str'>
列表类型 – list
  • 存储多个元素,使用[]包含
l = [1, 2, 3]
print(l, type(l))  # [1, 2, 3]<class 'list'>
元组类型 – tuple
  • 存储多个元素,使用()包含
t = (1, 2, 3)
print(t, type(t))  # (1, 2, 3) <class 'tuple'>
字典类型 – dict
  • 存储键值对,key:value格式,使用{}包含
d1 = {'数学': 90, '语文': 80}
print(d1, type(d1))  # {'数学': 90, '语文': 80} <class 'dict'>
集合类型 – set
  • 存放不重复的元素,使用{}包含
c1 = {1, 2, 3, 4, 4, 3, 2, 1}
print(c1, type(c1))  # {1, 2, 3, 4} <class 'set'>

数据类型的转换

  • 每一种数据类型都对应一个函数

  • int() float() bool() str() list() tuple() dict() set()

  • 函数的作用就是将其他数据类型转换为指定的数据

  • int()

    • 将字符串形式的整数转化为整型
    a = '10'
    b = int(a)
    print(b, type(b))   # 10 <class 'int'>
    
  • float()

    • 将字符串形式的整数或小数 转化为浮点型
    a = '10'
    b = float(a)
    print(b, type(b))  # 10.0 <class 'float'>
    
    a = '1.1'
    b = float(a)
    print(b, type(b))  # 1.1 <class 'float'>
    
  • bool()

    • 将数值转化为布尔类型 非0即为True
  print(bool(10))   # True
  print(bool(-10))  # True
  print(bool(0))    # False
  • 将容器型数据转化为布尔类型 非空即为True
print(bool(''))       # False
print(bool('     '))  # True
print(bool([]))       # False
print(bool([1, 2]))   # True
  • str()

    • 将整数或者小数 转化为字符串类型 【列表、元组、字典、集合都可以转化为字符串类型】

      a = 10
      b = str(a)
      print(b, type(b))  # 10 <class 'str'>
      
      a = 1.1
      b = str(a)
      print(b, type(b))  # 1.1 <class 'str'>
      
      a = [1, 2, 3]
      b = str(a)
      print(b, type(b))  # [1, 2, 3] <class 'str'>
      
      a = (1, 2, 3)
      b = str(a)
      print(b, type(b))  # (1, 2, 3) <class 'str'>
      
      a = {'数学': 90, '语文': 80}
      b = str(a)
      print(b, type(b))  # {'数学': 90, '语文': 80} <class 'str'>
      
      a = {1, 2, 3, 4, 4, 3, 2, 1}
      b = str(a)
      print(b, type(b))  # {1, 2, 3, 4} <class 'str'>
      
      a = True
      b = str(a)
      print(b, type(b))  # True <class 'str'>
      
      

输入输出函数

  • print() 把结果输出在控制台或者文件
a = b = c = 1
# 输出函数 print()
# *args 可变参数 打印的时候 可以打印一个内容 可以打印多个内容 可以不打印
print(a)
print(a, b)
print(a, b, c)
print()  # 换行的操作
# sep=' '   默认参数 打印多个内容 之间的分隔 默认是空格
print(a, b, c, sep='-')  # 1-1-1
# end='\n'   结束符 默认是\n 换行
print(a, end='---')
print(b)  # 1---1
# file=None   输出到的位置 默认输出到控制台 也可以输出文件
f = open('./demo.txt', 'w', encoding='utf-8')
print('哈哈哈', file=f)   # 出现deno.txt文件
f.close()

  • input() 把键盘输入的内容传递到程序中
# 输入函数 input(提示语)    返回的是字符串类型
age = input('请输入一个年龄:')
print(age, type(age))  # <class 'str'>
print(int(age) + 10)  # age=int(input('请输入一个年龄:'))

运算符

算术运算符

符号表示含义
+对数值:求和
对字符串:拼接
-对数值:求差
*对数值:求积
对字符串:将字符串的内容进行重复
/对数值:求商
结果是浮点型
除数不能为0
//对数值:求整数部分
10//3=3
除数不能为0
%对数值:求余数
10%3=1
除数不能为0
**对数值:求幂数 5**3 — 5的3次方
可间接实现开方
# +
print(3 + 5)          # 8
print(1.2 + 1.3)      # 2.5
print('abc' + 'cde')  # abccde

# -
print(10 - 5)         # 5
print(5 - 1.2)        # 3.8

# *
print(5 * 3)          # 15
print(10 * 3)         # 30
print('abc' * 2)      # abcabc

# /  结果数浮点型  除数不能为0
print(4 / 2)          # 2.0
# print(10/0)         #报错 除数不能为0


# //  整除
print(10 // 3)        # 3

# %  取余
print(10 % 3)         # 1

# ** 求幂数
print(5 ** 2)         # 25
# 间接开方 **0.5 **1/2
print(25 ** 0.5)      # 5.0
print(25 ** 1 / 2)    # 12.5  优先级

# 例题 分别获取num中各个位上的数字
# 获取方式  // %
num = 12345
# 12345%10  ---商1234  余5
gw = num // 1 % 10
print(gw)
# 12345//10%10  ---商123  余4
sw = num // 10 % 10
print(sw)
# 12345//100%10  ---商12  余3
bw = num // 100 % 10
print(bw)
# 12345//1000%10  ---商1  余2
qw = num // 1000 % 10
print(qw)
# 12345//10000%10  --- 余1
ww = num // 10000 % 10
print(ww)

# 获取某一位上的数字 num//这一位的权重 %10
# 获取某个整数的个位 num%10

# 练习  键盘输入一个三位数 求各个位上的和
a = int(input('请输入一个三位数:'))
print(a % 10 + a // 10 % 10 + a // 100)

# 练习 键盘输入一个三位数 获取的是三位数各个位上的立方和
a = int(input('请输入一个三位数:'))
print(((a % 10) ** 3) + ((a // 10 % 10) ** 3) + (a // 100) ** 3)

# 键盘输入三位数 获取这个三位数的反序数
a = int(input('请输入一个三位数:'))
gw = a % 10 * 100
sw = a // 10 % 10 * 10
bw = a // 100
print(gw + sw + bw)

赋值运算符

符号含义
=变量名 = 值
复合赋值运算符
+=a += 1
a = a+1
-=a -= 1
a = a-1
*=a *= 2
a = a*2
/=a /= 2
a = a/2
//=a //=2
a = a//2
%=a %= 2
a = a%2
**=a **=2
a = a**2
# 变量先定义在使用
a = 10

# +=
a += 1
print(a)  # 11

# -=
a -= 1
print(a)  # 10

# *=
a *= 2
print(a)  # 20

# /=                     /:除完是小数
a /= 4
print(a)  # 5.0

# //=
a //= 2  # 没有小数参与运算 结果是整数  有小数参与运算  结果是浮点
print(a)  # 2.0

# %=
a %= 3  # 没有小数参与运算 结果是整数  有小数参与运算  结果是浮点
print(a)  # 2.0

# **=
a **= 3  # 没有小数参与运算 结果是整数  有小数参与运算  结果是浮点
print(a)  # 8.0

# 应用于字符串
a = 'abc'
a += 'd'
print(a)  # 'abcd'

a *= 2
print(a)  # 'abcdabcd'

if (i % 4 == 0 and i % 100 != 0) or (i % 400 == 0): # 闰年的判断
    pass

比较运算符

  • 判断两个数据的大小关系或者是否相等,返回结果是布尔值
符号含义
>判断前者是否大于后者
>=判断前者是否大于或者等于后者
<判断前者是否小于后者
<=判断前者是否小于或者等于后者
==判断前者是否等于后者
!=判断前者是否不等于后者
  • 对字符串比较大小

    • 按照相同位置逐个比较,直到比较出大小
    • 逐个比较,比较的是对应的十进制数据
    • ‘a’ < ‘b’ — 97 < 98
      • 获取某个字符对应的十进制数据 ord(字符)
      • 获取十进制数据对应的字符 chr(十进制数据)
  • 编码encode

    • ascii码 128个字符 包含英文字母 阿拉伯数据 标点符号等
    • 0 – 48 A – 65 a – 97
    print(10==10)    #True
    print(10==10.0)    #True
    #  !=
    print(10!=5)       #True
    
    #字符串比较大小
    print('Z'>'A')     #True
    print(ord('Z'))    #90
    print(ord('A'))    #65
    
    print('你'>'我')    #False
    print(ord('你'))     #20320
    print(ord('我'))    #25105
    
    
    # 获取十进制数据对应的字符
    print(chr(97))   #a
    print(chr(1201))  
    
    #两个字符串比较大小
    print('baaaaaaaaaaaaa'>'azzzzzzzzzzzzzzz')   #True
    
    # 练习 键盘输入一个小写英文字母 输出对应的大写字母
    a=input('请输入一个小写字母:')
    #获取小写英文字母的十进制数
    b=ord(a)-32
    print(chr(b))
    
    
    #练习 键盘输入一个大写英文字母 输出对应的小写英文字母
    a=input('请输入一个大写字母:')
    print(chr(ord(a)+32))
    

逻辑运算符

  • 结果是布尔值
符号含义
and逻辑与
and 左右两边的条件同时成立,结果才成立
or逻辑或
or 左右两边的条件有一个成立,结果就成立
not逻辑非
对结果取反
# and     广义化是布尔值
print(10 > 5 and 10 > 9)  # True
print(10 > 5 and 10 < 9)  # False

# or
print(10 > 5 or 10 < 9)  # True
print(10 < 5 or 10 < 9)  # False

# not
print(not (10 < 9))  # True
print(not (9 > 5))  # False

# 键盘输入一个整数 判断这个整数 各个位上的和 是不是偶数 并且  个位数是偶数
num = int(input('请输入一个整数:'))
bw = num // 100 % 10
sw = num // 10 % 10
gw = num % 10
res = bw + sw + gw
print(res % 2 == 0 and gw % 2 == 0)

成员运算符

  • 结果是布尔值

    符号含义
    in判断数据是否在序列中 【容器型的数据】
    not in判断数据是否不在序列中
# in
# 数据是否为字符串的子串
print('a' in 'abc')  # True
print('b' in 'abc')  # True
print('c' in 'abc')  # True
print('ab' in 'abc')  # True
print('bc' in 'abc')  # True
print('abc' in 'abc')  # True
print('ac' in 'abc')  # False

# 数据是否为列表中的元素
print(1 in[1,2,3])
print(2 in[1,2,3])
print([1,2] in[1,2,3])


# not in
print('a' not in 'abc')  # False

海象运算符

print((a:=5)**2)   # :=

身份运算符

判断两个数据的内存地址是否一直,查看数据内存地址的函数 id()

符号含义
is判断两个数据的内存地址是否相同
is not判断两个数据的内存地址是否不相同

代码在cmd中执行,pycharm中做了优化,看不出结果

内存结构中常量池:存储实际的时候,首先会在常量池检查有没有这个数据,如果有,直接使用这个数据的内存地址,如果没有,开辟内存进行存储,把数据的内存地址给变量名

常量池中的数据:[-5,256](-5到256)的小整数 两个布尔值 空值None 不含有特殊符合的字符串

位运算符

  • 计算机运算的时候操作的是二进制数据,二进制数据有三种形态:原码、反码、补码【实际操作】

  • 对于整数来书,原码、反码、补码一样

  • 对于负数来说,

    • 原码:将正数原码的最高位置为1【最高位是符号位】
    • 反码:在原码的基础上,除最高位外,按位取反
    • 补码:在反码的基础上,+1
    原码、反码、补码
    十进制9--二进制 0b0000 1001
    	原码、反码、补码  0b0000 1001
    十进制-9
    	原码:0b1000 1001
    	反码:0b1111 0110
    	补码:0b1111 0111
    十进制-15
    	原码:0b1000 1111
    	反码:0b1111 0000
    	补码:0b1111 0001
    
    符合含义
    &按位与
    相投位上都是1,该位结果就是1
    |按位或
    相投位上有一个位1,该位结果就是1
    ^按位异或
    相投位上,不同为1,相同为0
    ~按位取反
    0变1,1变0
    <<按位左移
    将数据向左移动指定位数,右边空出补0
    >>按位右移
    将数据向右移动指定位数,左边空出补0
    6 & 7
    6二进制 0000 0110
    7二进制 0000 0111
    -----------------
    	   0000 0110 -- 6
    
    6 | 7
    6二进制 0000 0110
    7二进制 0000 0111
    -----------------
    	   0000 0111 -- 7
    	   
    6 ^ 7
    6二进制 0000 0110
    7二进制 0000 0111
    -----------------
    	   0000 0001 -- 1
    	   
    ~ 6
    6二进制 0000 0110
    -----------------
    	   1111 1001  --补码 ----原码
    	   1111 1000   反码
    	   1000 0111   原码  -7
    	   
    <<
    3按位左移两位
      0000 0011 -- 4
      0001 0000 -- 16
      
      规律 按位左移后的结果 = 数值 * 2的多少次幂
      
    >>
    32按位右移3位
      0010 0000  -- 32
      0000 0100  -- 4
      
      规律 按位右移后的结果 = 数值 // 2的多少次幂
    

字符串的格式化占位

  • %占位 %传值

    • 有几个未知数,用%填充几个数据
    • 占位符
      • %d – 整数
      • %f – 小数
      • %s – 任意类型的数据
  • {}占位 format进行传值

  • f修饰符进行修饰,{}占位,直接在{}中进行传值

    '''本金10000元存入银行,年利率是千分之三,每过1年,将本金和利息相加作为新的本金。计算5年后,获得的本金是多少'''
    year = 0
    m = 10000
    while year < 5:
        m = m + m * 0.003
        year += 1
    print('获得的本金是多少{:.2f}'.format(m)) # 三种保留几位小数的方法 保留几位小数就.几f
    print(f'获得的本金是多少{m:.2f}')
    print(f'获得的本金是多少{m:.2%}')  # 保留两位百分数
    print('获得的本金是多少%.2f' % m)
    

print(f’获得的本金是多少{m:,}') # 没三个一分隔




## 流程控制语句

### 顺序语句

- 执行顺序是从上向下,逐行解释代码

### 分支语句

- 根据不同的需求,出现不同的行为,由三个关键字组成`if  elif  else` ,组成了三种不同的分支语句 

- 单分支语句

- ```
  语法结构 
  
  if 条件语句:
  	满足条件语句执行的代码  
  	
  if 有100块钱:
  	吃烤羊 
  ```

- 双分支语句

- ```
  语法结构 
  
  if 条件语句:
  	满足条件执行的内容
  else:
  	条件不满足执行的内容  
  	
  if 有100块钱:
  	吃烤羊
  else:
  	吃肉夹馍
  ```

- 多分支语句

- ```
  语法结构 
  
  if 条件语句1:
  	满足条件1执行的代码  
  elif 条件语句2:
  	不满足条件1,但是满足条件2执行的代码
  elif 条件语句3:
  	不满足条件1和条件2,但是满足条件3执行的代码 
  else:
  	以上条件都不满足执行的代码  
  	
  	
  if 超过2000块钱:
  	吃帝王蟹
  elif 超过1000块钱:
  	吃烤全羊
  elif 超过500块钱:
  	吃海底捞
  elif 超过200块:
  	吃手抓饭
  else:
  	吃肉夹馍
  ```

- 三元运算符

```python
num = int(input('请输入一个整数'))
print(num ** 0.5 if num > 0 else num ** 2)
res = num ** 0.5 if num > 0 else num ** 2
print(res)
print(num**0.5) if num>0 else print(num**2)
  • 分支嵌套

    • 在其中一个分支下,又分了不同的情况
    '''输出2000~3000 年之间所有的闰年,要求每输出8个年份值就换行, 不换行时使用空格隔开'''
    num = 0
    for i in range(2000, 3001):
        if (i % 4 == 0 and i % 100 != 0) or (i % 400 == 0):
            num += 1
            print(i, end=' ')
            if num == 8:
                num = 0
                print()
    

循环语句

  • python中的循环语句有两种,for-in循环while循环
for-in循环
  • 语法结构
    for 变量名 in 序列【容器型】:
    	循环体  
    
    执行流程:
    	首先进入容器中,检查有没有下一个数据,如果有,把数据取出并赋值给变量名,进入循环中执行代码,循环体中执行完成之后,再次进入容器中检查有没有下一个数据,如果没有,结束循环  	
    
  • range函数 – 产生等差数列

    用法 
    range(start,stop,step)
    
    方式一 产生 从0到结束 【不包含结束】
    range(stop)
    省略开始  代表从0开始
    省略步长  代表步长为1  
    range(10) -- 0 1 2 3 4 5 6 7 8 9 
    
    方式二  产生的是 从开始 到结束 【不包含结束】
    range(start,stop)
    省略步长  步长为1 
    range(5,10) -- 5 6 7 8 9 
    
    方式三  产生的是 从开始到结束 按照指定的步长 【不包含结束位置】
    range(start,stop,step)
    根据步长正负
    	步长为正  产生的是递增序列  数字逐渐变大  从小往大  开始 < 结束 
    	步长为负  产生的是递减序列  数字逐渐变小  从大往小  开始 > 结束 
    	
    	如果不满足上述条件 产生的是空序列 
    
    range(0,10,2) -- 0 2 4 6 8 
    range(10,0,-2) -- 10 8 6 4 2 
    
  • for - else结构

  • 语法结构
    
    for 变量名 in 序列:
    	循环体 
    else:
    	当且仅当序列中没有数据可遍历时,执行else结构代码块中的内容 
    	如果break结束的循环 不会进入else中 
    
'''键盘输入一个字符串,判断是否纯中文组成'''
str_s = str(input('请输入一个字符串:'))
for i in str_s:
    if '\u4e00' <= i <= '\u9fa5':       #是否为汉字的判断条件
        a = True
    else:
        a = False
if a == True:
    print('是纯中文组成')
else:
    print('不是纯中文组成')
'''键盘输入一个小写英文字母
如果小写字母在 a-w之间 输出 内容a -- d   b--e  c--f ... w -- z
如果是xyz   输出 x--a  y--b  z--c'''


letter = input('请输入一个小写英文字母: ')
if 'a'<=letter<='w':
    print(chr(ord(letter) + 3))
elif 'x'<=letter<='z':
    print(chr(ord(letter)-23))
import string
'''键盘输入一个字符串 判断是否英文字母组成'''
str_s = input('输入一个字符串')
for i in str_s:
    if i not in string.ascii_letters:     #ascii_letters 纯英文
        print('不是纯英文字母组成')			#string.digits 纯数字
        break							  #ascii_uppercase 大写英文
else:									  #ascii_lowercase 小写英文
    print('是纯英文字母组成')
while循环`
语法结构 

while 条件语句:
	循环体  
		
执行流程

验证条件是否成立,如果条件成立,进入循环体中执行代码,当循环体中内容执行完成之后,再次验证条件是否成立,如果条件不成立,结束循环 

假如循环的条件语句一直成立,一直循环,形成死循环 【避免】

应用场景
1. 有明确的循环次数,for-in循环可以实现,实现比while更简单 
2. 没有明确的循环次数,循环的条件 【主要的应用场景】

while 碗里有饭:
	一直吃  
num = random.randint(1, 100)  # 1到100的随机数
print(num)
while True:			# 一直循环 死循环
    num_s = int(input('输入一个数'))
    if num_s > num:
        print('猜大了')
    elif num_s < num:
        print('猜小了')
    else:
        print('猜对了')
        break		# 跳出循环

'''2. 一个球从100米处落下 每次落地后反弹回原高度的一半,问落地几次后反弹高度不足10米'''
h = 100
num = 0
while h > 10:
    h = h / 2
    num += 1
print(h, num)
两个关键字
  • break 结束循环
  • continue 结束本次循环 进入下一次循环 continue后面的代码不会被执行
import random

num = random.randint(1, 100)
print(num)
# 设置变量记录次
c = 0
# 只要猜不对  一直猜
# 循环做的事情  猜数  判断
# 设置猜数范围中的初始值
start = 1
stop = 100
while True:
    c += 1
    guess = int(input(f'请输入{start}-{stop}中的数字'))
    if start <= guess <= stop:
        if guess > num:
            # 开始和结束 做对应的变化
            stop = guess - 1
            print('猜大了')
        elif guess < num:
            start = guess + 1
            print('猜小了')
        else:
            print(f'总共用了{c}次猜对了!')
            # print(c)
            # 分类  次数  <3  获取奖金100w    3-8之间  获取奖金100块  否则  白瞎了2块钱
            if c < 3:
                print('获取奖金100w')
            elif 3 <= c < 8:
                print('获取奖金100块')
            else:
                print('白瞎了2块钱')
            # break
            # 询问是否继续游戏
            # 回答 键盘输入
            answer = input('是否继续游戏 y/n')
            if answer == 'y':
                # 重新产生随机数
                num = random.randint(1, 100)
                print(num)
                # 次数 重置为0
                c = 0
                # 开始 数据  和结束数据 重置
                start = 1
                stop = 100
            elif answer == 'n':
                print('结束游戏')
                break
    else:
        print('输入数据超出范围')

常见的数据结构

字符串

转义字符

\n -- 换行 \t -- tab键

\ 对一些特殊符号进行转义

\n newline -- 换行 \t tab -- tab键 横向制表符 \r return -- 回车 \' -- ' \" -- " \\ -- \ \v -- 纵向制表符 \f -- 换页 \u -- unicode字符

防止转义 两种方式:加\ \\ -- \ 修饰符 r R

# \n 光标定位到下一行的行首
print('a\nb')
print(len('a\nb'))   # 3
# \t
print('a\tb')
print(len('a\tb'))   # 3
# \r  return   光标定位到本行行首   如果\r之前有内容 把前面的内容清空
print('ab\rc')   # c
# \v   \f 控制台上没有效果
print('a\vb')
print('a\fb')
# \u
print('\u4e00')  # 一
# \'  \"  \\
print('i\'m fine')  # i'm fine
# \\  win  路径
print('C:\\Users\\86166\\Documents\\上课资料\\分享')   # C:\Users\86166\Documents\上课资料\分享
# 不对内容进行转义   防止转义  第一种 \\ -- \       第二种 使用修饰符进行修饰 r R
print(r'C:\Users\86166\Documents\上课资料\分享')   # C:\Users\86166\Documents\上课资料\分享
print(r'a\nb')  # a\nb
print('a\\nb')  # a\nb
print(len('a\\nb'))   # 4    \n换行  一个字符  \\n -- \n 2个字符
print(len(r'a\nb'))  # 4
print(R'\u4e00')
概念及特点
  • 概念:包含零个或者多个字符 的 有序不可变 序列
  • 特点:
    • 有序
      • 添加顺序和显示顺序一致
      • 添加元素时,会为这个元素设置编号,编号是0开始的,又被称为索引、下标、脚标
    • 不可变
      • 内存地址不变的情况下,内容不会发生变化
      • 内容变了,内存地址就变了
      • 查看变量的内存地址 id(变量)
定义字符串
  • 使用引号包含 一对单引号 一对双引号 一对三引号 【预编译文本】
  • 使用str() 构造
支持的运算符
符号含义
+拼接
*重复
+=s += ‘d’
*=s *= 2
比较比较规则:相同位置逐个比较,直到比较出大小
比较的是字符对应的十进制数据 ord() chr()
成员运算符in not in
数据 in 字符串中
字符串的索引和切片
  • 获取序列长度 len(序列)

  • 索引 获取序列的元素 序列[索引] 字符串对象[索引]

    • 正向索引

      • 从左向右数
      • 从0开始 到 长度-1 结束
    • 负向索引

      • 从右向左数
      • 从 -1开始 到 -长度 结束
    • 成绩单
      
      1  小花   第1名   倒数第6名
      2  小明
      3  小刚   第3名   倒数第4名 
      4  小绿
      5  小兰
      6  小红   第6名    倒数第1名
      
      
      s = 'abcde'
      	'abcde'
      正向  01234
      负向  54321   -
      
      获取某个索引对应的字符  字符串对象[索引]
      
      import string
      
      s = 'abcdefg'
      # 获取s中的第一个字符  索引 正向0    负向-7
      print(s[0])
      print(s[-7])
      
      # 获取s中的最后一个字符  索引 正向6  负向-1
      print(s[6])
      print(s[-1])
      
      s = 'asdasdsadasdsawqewqsadxzceqwdasctrdgf'
      # 正向 从0开始 到 长度-1结束  最后一个字符的正向索引 长度-1
      print(len(s))
      print(s[len(s) - 1])
      # 负向
      print(s[-1])
      
      # 获取第一个字符
      # 正向 0
      print(s[0])
      # 负向索引  从-1开始 到 -长度结束  第一个字符对应的负向索引位-长度
      print(s[-len(s)])
      
      # 总结规律
      # 正向
      # 获取第n个字符 对应的索引是 n-1 s[n-1]
      # 负向
      # 获取第n个字符 对应的索引  -长度+(n-1)
      
      # 正向
      # 获取倒数第n个  对应的索引 长度-n
      # 负向
      # 获取倒数第n个   对应的索引  -n
      s = string.ascii_uppercase
      # s='ABCDEFG......Z'
      print(s)
      # 获取s中的第10个字符
      # 正向
      print(s[9])
      # 负向
      print(s[-len(s) + 9])
      
      # 获取s中的倒数第3个
      # 正
      print(s[len(s) - 3])
      # 负
      print(s[-3])
      
      s = '12345abcde'
      # 获取s中的第一个字符
      print(s[0])
      print(s[-len(s)])
      # 获取s中的第3个字符
      print(s[2])
      print(s[-len(s) + 2])
      # 获取s中的最后一个字符
      print(s[-1])
      print(s[len(s) - 1])
      # 获取s中的倒数第3个字符
      print(s[-3])
      print(s[len(s) - 3])
      
      s = 'ABCDabcd1234'
      # 获取s中的第5个字符
      print(s[4])
      print(s[-len(s) + 4])
      # 获取s中倒数第5个字符
      print(s[-5])
      print(s[len(s) - 5])
      # 获取s中的第7个字符
      print(s[6])
      print(s[-len(s) + 6])
      # 获取s中倒数第7个字符
      print(s[-7])
      print(s[len(s) - 7])
      
  • 切片

    • 根据索引来定位范围,提取范围中的子串,切片的操作 序列[起始位置:结束位置:步长]

    • 采用正向索引和负向索引都可以 不包含结束位置

    • 根据步长的正负性分为两种 abcde

      • 正向切片
        • 从左向右提取子串
        • 步长为正
        • 要求 起始索引定位的字符 在 结束索引定位字符的 左边
      • 负向切片
        • 从右向左提取子串
        • 步长为负
        • 要求 起始索引定位的字符 在 结束索引定位字符的 右边
    • 切片中有些内容是可以省略的

      • 省略 :步长 序列[起始:结束]

        • 代表步长为 1 ,表示的步长为正,从左向右提取
      • 省略 结束索引 序列[开始索引::步长]

        • 步长为正 表示从左向右获取 表示 到最右边结束
        • 步长为负 表示从右向左获取 表示 到最左边结束
      • 省略 起始索引 序列[:结束索引:步长]

        • 步长为正 表示从左向右获取 表示 从最左边开始
        • 步长为负 表示从右向左获取 表示 从最右边开始
      • 省略 起始索引和结束索引 序列[::步长]

        • 步长为正 表示从左向右取 代表从最左边开始 到最右边结束

          • 序列[::1] 序列[:] 序列复制
        • 步长为负 表示从右向左取 表示 从最右边开始 到最左边结束

          • abcd
          • 序列[::-1] 字符串反转
          # 操作   字符串【起始索引:结束索引:步长】    (不包含结束位置)
          s = '0123456789'
          # 索引 用来定位某个位置
          # 切片  根据索引定位范围 获取的是范围中的子串
          # 获取s中 第一个字符 到第五个字符
          print(s[0:5:1])  # 01234
          # 省略:步长  代表步长为1
          print(s[0:5])
          # 有步长获取
          print(s[0:5:2])  # 024
          
          # 负向切片  从右向左获取
          s = '0123456789'
          # 从右向左获取 倒数第5个
          print(s[-1:-5:-1])
          
          # 从右向左获取 倒数5个 每隔一个取一个
          print(s[-1:-6:-2])
          
          s = '床前明月光,疑是地上霜;举头望明月,低头思故乡'
          # 获取s中前10个字符
          print(s[0:10])
          # 从左向右获取第五个字符到第十个字符
          print(s[4:10])
          # 从右向左获取s中的最后10个字符
          print(s[-1:-11:-1])
          
          s = '床前明月光,疑是地上霜;举头望明月,低头思故乡'
          # 可省略内容
          # 步长  代表步长为1
          
          # 省略结束位置  到xxx结束  正向还是负向
          # 从左向右取  到最右边结束
          # 取s中第10个字符到最后
          print(s[9::1])
          # 从右向左取  到最左边结束  步长为负
          # 从右向左获取前10个字符
          print(s[9::-1])
          
          # 省略起始索引  从xxx开始
          # 从左向右获取  从最左边开始
          # 获取前10个字符
          print(s[0:10:1])
          print(s[0:10])
          print(s[:10])
          # 从右向左获取  从最右边开始
          # 从右向左获取最后10个字符
          print(s[-1:-11:-1])
          print(s[:-11:-1])
          # 没有步长 步长为1 从左向右获取
          # 从最左边开始 到-11结束 不包含-11
          print(s[:-11])
          # 复制
          print(s[::1])
          print(s[:])
          # 反转
          print(s[::-1])
          
          s = 'how are you thank you very much'
          # 获取s中的前5个字符
          print(s[0:5])
          # 从右向左获取s中的前5个字符
          print(s[4::-1])
          # 从左向右获取s中的最后5个字符
          print(s[26::])
          # 从右向左获取s中的最后5个字符
          print(s[-1:-6:-1])
          # 将s的内容复制
          print(s[:])
          # 将s中的内容反转
          print(s[::-1])
          # 获取s中的第5到第10个字符 不包含第10个
          print(s[4:9:1])
          # 从右向左获取s中的第5到第10个字符
          print(s[9:3:-1])
          print('--------------------------')
          
          # 练习
          s = 'how are you thank you very much'
          # 从左向右获取前10个字符
          print(s[:10:1])
          # 从右向左获取前10个字符
          print(s[9::-1])
          # 获取最后一个字符
          print(s[-1])
          # 获取第5个字符
          print(s[4])
          # 从左向右获取后10个字符
          print(s[-10::1])
          # 从右向左获取后10个字符
          print(s[-1:-11:-1])
          # 获取第7-第15个字符 包含第15个
          print(s[6:15])
          # 从左向右获取整个字符串中每隔一个取一个
          print(s[::2])
          # 获取整个字符串中从后往左每隔一个取一个
          print(s[::-2])
          # 字符串的反转
          print(s[::-1])
          
字符串的遍历
  • 直接遍历字符串
  • 遍历索引 当和索引相关
  • 枚举遍历
# 获取s中g对应的索引
# 正向索引 0--长度-1结束  (len())
for i in range(0, len(s)):
    # range(0,len(s))  0 1 2 3 4 5 6 ... len(s)-1
    # i表示的是索引位置
    # 判断的是通过索引获取对应的字符s[i]
    if s[i] == 'g':
        print(i, end=' ')

print()
# 获取s中索引能被3整除或者能被2整除对应的字符
s = '0123456789'
for i in range(0, len(s)):
    if i % 2 == 0 or i % 3 == 0:
        print(s[i], end=' ')

print()
s = 'bJGjd12Gkaf'
# 获取s中大写英文字母对应的索引
for i in range(0, len(s)):
    if s[i] in string.ascii_uppercase:
        print(i, end=' ')
print()
# 获取s中索引是偶数 并且对应的字符为小写英文字母
for i in range(0, len(s)):
    if i % 2 == 0 and s[i] in string.ascii_lowercase:
        print(s[i], end=' ')

# 枚举遍历
s='ABCD'
for i in enumerate(s):
    # i 元组 两个元素  第一个元素 索引 第二个元素 字符
    print(i)

for a,b in enumerate(s):
    #前面接收到的是索引
    #后面接收到的是字符
    print(a,b)

s = 'bJGjd12Gkaf'
#获取s中大写英文字母对应的索引
for a,b in enumerate(s):
    if b in string.ascii_uppercase:
        print(a,end=' ')
print()
# 获取s中索引是偶数 并且对应的字符为小写英文字母
for a,b in enumerate(s):
    if a%2==0 and b in string.ascii_lowercase:
        print(b,end=' ')

print()
# 获取s中索引能被3整除对应的字符
for a,b in enumerate(s):
    if a%3==0:
        print(b,end=' ')
print()
# 获取字符 J 或者 j 对应的索引
for a,b in enumerate(s):
    if b=='j' or b=='J':
        print(a,end=' ')
字符串的操作
获取的操作

​ 获取某个子串在字符串中第一次出现的位置 字符串对象.find(子串)
​ 如果子串在字符串中存在,返回子串第一次出现的位置 【子串中的第一个字符的位置】
​ 如果子串在字符串中不存在,返回 -1

​ 获取某个子串在字符串中最后一次出现的位置 字符串对象.rfind(子串)
​ 如果子串在字符串中存在,返回子串最后一次出现的位置 【子串中的第一个字符的位置】
​ 如果子串在字符串中不存在,返回 -1

​ 获取某个子串在字符串中出现的次数 字符串对象.count(子串)
​ 如果子串在字符串中不存在,结果为0

#第一次出现的位置
s='abcdefgabcd'
print(s.find('a'))
print(s.find('abc'))
print(s.find('x'))

#最后一次出现的位置
print(s.rfind('a'))
print(s.rfind('abc'))
print(s.rfind('cb'))

#次数
print(s.count('a'))
print(s.count('abc'))
print(s.count('abcd'))
print(s.count('xyz'))

#判断子串在字符串中是否唯一
s='abcdeabc'
if s.count('abc')!=0:
    if s.count('abc')==1:
        print('唯一')
    else:
        print('不唯一')
else:
    print('内容不存在')

#第一次出现的位置=最后一次出现的位置
s='abcdeabc'
if s.find('abc')!=-1:
    if s.find('abc')==s.rfind('abc'):
        print('唯一')
    else:
        print('唯一')
else:
        print('内容不存在')
获取的操作 
	获取某个子串在字符串中第一次出现的位置 
		字符串.find(子串,起始索引,结束索引)   如果找不到 返回-1
		字符串.index(子串,起始索引,结束索引)  如果找不到 报错
	获取某个子串在字符串中最后一次出现的位置 
		字符串.rfind(子串,起始索引,结束索引)   如果找不到 返回-1
		字符串.rindex(子串,起始索引,结束索引)  如果找不到 报错
	获取某个子串出现的次数 
		字符串.count(子串,起始索引,结束索引)
	解读:如果起始索引和结束索引不指定,在整个字符串中查找,如果指定起始索引和结束索引,在范围中查找,不包含结束位置
	
转换的操作
	字符串中的小写转大写  其他不变   字符串.upper()
	字符串中的大写转小写  其他不变   字符串.lower()
	字符串中的大写转小写 小写转大写 其他不变  字符串.swapcase()
	字符串中所有单词首字母大写 其他小写 其他内容不变  字符串.title()
	字符串的首字母大写 其他字母小写  其他内容不变  字符串.capitalize()
	
字符串的编码encode和解码decode 
	字符串.encode(编码方式)    gbk   utf-8
	字节串.decode(解码方式)
	
字符串判断的操作
	判断字符串中的内容是否纯数字组成    字符串.isdigit()
	判断字符串中的内容是否纯字母组成[字母 所有国家的语言]    字符串.isalpha()  
	判断字符串中的内容是否纯英文字母组成      字符串.encode('utf-8').isalpha() 
	判断字符串中的内容是否数字或字母组成[字母 所有国家的语言]   字符串.isalnum() 
			[纯数字  纯字母  数字+字母]
	判断字符串中的内容是否数字或英文字母组成   字符串.encode('utf-8').isalnum()
	判断字符串中的英文字母是否都是大写  		   字符串.isupper()
	判断字符串中的英文字母是否都是小写  		   字符串.islower()
	判断字符串是否每个单词的首字母大写 其他小写  字符串.istitle()
	判断字符串中的内容是否都是ascii中的        字符串.isascii()
	判断字符串是否以指定内容开头         字符串.startswith(指定内容)
	判断字符串是否以多个内容中的其中一个开始   
			字符串.startswith(元组)   字符串.startswith((指定内容1,指定内容2,指定内容3))
	判断字符串是否以指定内容结尾         字符串.endswith(指定内容)
	判断字符串是否以多个内容中的其中一个结尾
			字符串.endswith(元组)   字符串.endswith((指定内容1,指定内容2,指定内容3))
	
切割与拼接 
	将字符串按照指定的切割符号进行切割     字符串.split(切割符号,切割次数)
		如果不指定切割次数,有多少切割符号,切多少次 
		如果不指定切割符号,按照空白字符进行切割   \n  \t  \r  \v  \f  空格   
	将字符串按照指定的切割符号从右边开始进行切割  字符串.rsplit(切割符号,切割次数)    
	
	将序列中的内容拼成一个字符串 【要求序列中的元素是字符串类型】
		拼接符号.join(序列)   

替换的操作
	将字符串中的某些内容替换成新内容   字符串.replace(旧内容,新内容,替换次数)
		替换次数不指定,有多少旧内容,替换多少次

清除字符串两端的指定内容 
	字符串.strip(指定内容)
		如果内容不指定,默认清除的是左右两端的空白字符
清除字符串左边的指定内容
	字符串.lstrip(指定内容)
清除字符串右边的指定内容
	字符串.rstrip(指定内容)	
转换的操作

​ 将字符串中小写字母转化为大写 其他不变 字符串对象.upper()
​ 将字符串中大写字母转化为小写 其他不变 字符串对象.lower()
​ 将字符串中大写字母转化为小写 小写字母转化为大写 其他不变 字符串对象.swapcase()
​ 将字符串的首字母大写 其他英文字母小写 其他不变 字符串对象.capitalize()
​ 将字符中的每个单词的首字母大写 其他英文字母小写 其他不变 字符串对象.title()

s = 'How aRe You'
# 将小写转化为大写 其他不变
print(s.upper())  # HOW ARE YOU
# 将大写转化为小写 其他不变
print(s.lower())  # how are you
# 大转小 小转大
print(s.swapcase())  # hOW ArE yOU
# 首字母大写 其他字母小写
print(s.capitalize())  # How are you
# 每个单词的首字母大写 其他英文字母小写
print(s.title())  # How Are You
判断的操作

结果是布尔值
判断字符串是否纯数字组成 字符串对象.isdigit()
判断字符串是否纯字母组成【字母不仅指英文字母】 字符串对象.isalpha()
判断字符串是否数字或字母组成【纯数字 纯字母 数字+字母】 字符串对象.isalnum()
判断字符串中的英文字母是否都是大写 字符串对象.isupper()
判断字符串中的英文字母是否都是小写 字符串对象.islower()
判断字符串是否以指定内容开头 字符串对象.startswith(指定内容)
判断字符串是否以多个内容中的其中一个开头 字符串对象.startswith((指定内容1,指定内容2,指定内容3))
判断字符串是否以指定内容结尾 字符串对象.endswith(指定内容)
判断字符串是否以多个内容中的其中一个结尾 字符串对象.endswith((指定内容1,指定内容2,指定内容3))

# 判断是否纯数字组成
s = '12a'
print(s.isdigit())
# 判断是否纯字母组成  不仅指英文字母
s = 'hah你好'
print(s.isalpha())
# 判断是否数字或字母组成  纯数字 纯字母 数字+字母
s = 'adc你好123'
print(s.isalnum())
# 是否大写
s = 'ABC123'
print(s.isupper())
# 判断小写
s = 'abc123'
print(s.islower())
# 以xxx开头
s = 'abcdefg'
print(s.startswith('a'))
print(s.startswith('ab'))
print(s.startswith('abc'))
# 判断字符串是否以多个内容中的其中一个开头
print(s.startswith(('a', 'b', 'c')))
# 以xxx结尾
print(s.endswith('g'))
print(s.endswith('fg'))
print(s.endswith('efg'))
# 判断字符串是否以多个内容的其中一个结尾
print(s.endswith(('e', 'f', 'g')))
编码encode和解码decode

​ 编码方式
​ ascii 128个字符 单字节存储 1字节 = 8位
​ gb2312 中文 6000+ 中文汉字 采用双字节存储
​ gbk 中文2w+ 中文汉字 采用双字节存储
​ utf-8 中文汉字 采用三字节存储
​ 编码 字符串对象.encode(编码方式) 结果 字节数据
​ 解码 字节对象.decode(解码方式)
​ 用什么方式进行编码,就用什么方式进行解码 否则 会出现乱码或者报错

s='你好'
s1=s.encode('gbk')
print(s1)
s2=s.encode('utf-8')
print(s2)

#解码  将字节数据解码
print(s1.decode('gbk'))
print(s2.decode('utf-8'))
切割与拼接

​ 切割 字符串对象.split(切割符号) 产生的结果是列表
​ 拼接 拼接符号.join(序列) 结果是字符串 ‘ ’ ‘+’
​ 序列中的元素的数据类型是字符串类型

s = 'how are you'
# 用空格切割
l = s.split(' ')
print(l)

# 拼接       必须是字符串
print(' '.join(l))
print('+'.join(l))

列表

概念及特点
  • 概念:存储零个或者多个元素的 有序可变 序列,多个元素之间时候逗号分隔,列表中可以存储多种数据类型的数据,但是为了数据的统一性,存储的数据一般是同种数据类型的

  • 特点

    • 有序

      • 使用索引和切片获取元素
    • 可变

      • 内存地址不变的情况下,列表中的数据可以发生变化 【增 删 改】
      • 3楼22教室
      # 概念
      l = [1, 2, 3]
      print(l, type(l))
      # 可以存放多种数据类型
      l = [10, 1.1, True, 'abc', [1, 2, 3], (1, 2, 3), {'数学': 80}]
      print(l, len(l), type(l))
      
      # 特点
      # 有序
      print(l[0])
      print(l[-1])
      # 可变
      l = [1, 2, 3]
      print(l, id(l))
      # l中添加元素
      # 列表对象.append(元素)
      l.append(4)
      print(l, id(l))
      # 定义列表
      # 空列表 len=0
      l = []
      print(l, type(l), len(l))
      l = ['   ']
      print(l, type(l), len(l))
      l = list()
      print(l, type(l), len(l))
      # 非空列表
      l = [1, 2, 3, 4]
      print(l, type(l), len(l))
      l = list('abc')
      print(l)
      l=list(range(0,10))
      print(l)
      l1=[1,2,3]
      print(l1[0],type(l1[0]))
      l2=['1','2','3']
      print(l2[0],type[0])
      
定义列表
  • 使用[]包含
  • 使用list()构造
列表支持的运算符
符号含义
+合并两个列表中的数据 产生一个新列表 【内存地址变化 称为新的】
*将列表中的元素重复n遍 产生一个新列表
+=s+=s1 在当前列表的基础上 合并序列
*=在当前列表的基础上 重复内容
成员运算符判断数据是否为列表中的元素
比较运算符相同位置逐个比较,直到比较出大小
[1,2,3] [4,5,6]
列表的索引和切片
  • 获取的操作和字符串是一样的

  • 列表中的数据可以修改的 获取再重新赋值

    • 列表对象[索引] = 值
    l=[12,34,56,78,90]
    #获取第一个元素
    print(l[0])
    #获取最后一个元素
    print(l[-1])
    #获取前两个
    print(l[:2])
    #获取最后三个
    print(l[-3:])
    #复制
    print(l[:])
    #反转
    print(l[::-1])
    #从右向左获取最后3个元素
    print(l[-1:-4:-1])
    #列表中的数据可以修改  获取在赋值
    l=[12,34,56,78,90]
    print(l,id(l))
    #修改l中的第2个元素
    l[1]=100
    print(l,id(l))
    
列表的遍历
  • 直接遍历列表
  • 遍历索引
  • 枚举遍历
import string

l = ['how', 'are', 'you', 'i', 'am', 'fine', 'thanks']
# 获取l中元素长度大于3
# 空列表
l1 = list()
for i in l:
    # i 指列表中的元素 单词 字符串类型
    # print(i,type(i))
    if len(i) > 3:
        # l1+=[i]
        l1.append(i)
print(l1)

# 获取列表中含有字母o的单词 存放在列表中
l2 = list()
for i in l:
    if 'o' in i:
        l2.append(i)
print(l2)
# 获取列表中以e结尾的单词存放在列表中
l3 = list()
for i in l:
    if i[-1] == 'e':
        l3.append(i)
print(l3)
# 获取列表中 以h 或者 t 开头的单词存放在列表中
l4 = list()
for i in l:
    if i[0] == 'h' or i[0] == 't':
        l4.append(i)
print(l4)

# 将列表中的每个单词转化为大写 存放在列表中
l5 = list()
for i in l:
    l5.append(i.upper())
print(l5)

# 将l1中的单词 使用空格拼接
# 字符串的拼接 拼接符号.join(序列)
print(' '.join(l1))

# 遍历索引
l = ['how', 'are', 'you', 'i', 'am', 'fine', 'thanks']
# 获取l中长度为3的元素对应的索引
# 从0开始  到len-1结束
for i in range(0, len(l)):
    if len(l[i]) == 3:
        print(i)
# 枚举遍历
for pos, ele in enumerate(l):
    # pos 索引  ele 元素
    if len(ele) == 3:
        print(pos)

# 获取l中包含e的单词对应的索引
for pos, ele in enumerate(l):
    if 'e' in ele:
        print(pos)
# 获取l中以s结尾的单词对应的索引
for pos, ele in enumerate(l):
    if ele[-1] == 's':

        print(pos,end='   ')
# 获取l中索引位偶数 且 对应的单词长度为偶数 的元素
for i in range(0, len(l)):
    if i % 2 == 0 and len(l[i]) % 2 == 0:
        print(l[i])


l = [15,46,125,91,3325,872]
# 获取l中的所有的偶数 存放列表
l1=[]
for i in l:
    if int(i)%2==0:
        l1.append(i)
print(l1)
# 获取l中含有数字1的元素 存放列表
l2=[]
for i in l:
    if '1' in str(i):
        l2.append(i)
print(l2)
# 获取l中最高位数字为偶数的元素 存放列表
l3=[]
for i in l:
    if int(str(i)[0])%2==0:
        l3.append(i)
print(l3)
# 将l中的元素使用+拼接
l1=[]
for i in l:
    l1.append(str(i))
print('+'.join(l1))
列表的操作

增加元素
列表中追加元素 列表对象.append(元素)
列表的指定位置添加 列表对象.insert(索引,元素)
原有的索引位置及以后的所有元素整体向后移动一位,元素填充空位

删除元素
删除列表的最后一个元素 列表对象.pop()
删除列表中指定位置的元素 列表对象.pop(索引)
删除列表中的指定数据 列表对象.remove(数据) 只能删除找到的第一个

l = [1, 2, 3, 4]
print(l, id(l))
# 添加元素
# 追加
l.append(5)
print(l, id(l))  # [1, 2, 3, 4, 5]
l.append(6)
print(l, id(l))  # [1, 2, 3, 4, 5, 6]
# 指定内容插入
l.insert(3, 100)
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6]
# 合并序列   等同于  +=
l.extend(range(1, 5))
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2, 3, 4]
# 删除
# 删除最后一个
l.pop()
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2, 3]
l.pop()
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2]
# 删除指定位置的元素
l.pop(2)  # 2  指的是索引
print(l, id(l))  # [1, 2, 100, 4, 5, 6, 1, 2]
# 删除指定元素   元素的值
l.remove(1)  # 1 指的是元素的值 是  1
print(l, id(l))  # [2, 100, 4, 5, 6, 1, 2]
# 清空
l.clear()
print(l, id(l))  # []

修改元素
获取再赋值
l[0] = 100

获取
获取某个元素出现的次数 列表对象.count(元素)

l = [1, 2, 3, 4, 1, 2]
print(l, id(l))
# 第一次出现的位置
print(l.index(1))  # 0
# print(l.index(5))   # ValueError: 5 is not in list
# 统计次数
print(l.count(1))  # 2
# 其他操作
# 复制   产生一份新的
l1 = l.copy()
print(l1)
# 排序   改变的是列表本身
l.sort()
print(l, id(l))
l.sort(reverse=True)
print(l, id(l))
print('--------------------分割线--------------------')
# 反转
l = [1, 2, 3, 4, 1, 2]
print(l, id(l))
l.reverse()  # 会影响列表本身
print(l, id(l))
print('--------------------分割线[::-1]--------------------')
#
l = [1, 2, 3, 4, 1, 2]
print(l, id(l))
l1 = l[::-1]
print(l1)
print(l)
增加 
	列表的末尾追加一个元素   列表.append(元素)
	列表中插入一个元素    列表.insert(索引位置,元素)    原有索引位置及以后的元素整体向后移动一位   		12534 
	合并序列   等同于 +=      列表.extend(序列)

删除 
	删除最后一个末尾的元素    列表.pop()
	删除指定索引位置的元素    列表.pop(索引位置)   
	删除指定的元素           列表.remove(元素)   如果列表中有多个元素,删除找到的第一个 
	清空列表 结果是一个空列表  列表.clear()

修改 
	获取再赋值   索引和切片部分 

获取  
	获取第一次出现的位置  列表.index(元素,起始索引,结束索引)
	获取元素出现的次数    列表.count(元素)

其他
	拷贝列表    列表.copy() 
	对列表排序  列表.sort()  默认是升序排序 
			  列表.sort(reverse = True)  降序排序    reverse  反转 
	列表的反转   列表.reverse() 
			    列表[::-1]
			区别:列表.reverse() 影响的是原列表  
				 列表[::-1]     不影响原列表 产生一个新列表 
l = [1, 2, 3, 4]
print(l, id(l))
# 添加元素
# 追加
l.append(5)
print(l, id(l))  # [1, 2, 3, 4, 5]
l.append(6)
print(l, id(l))  # [1, 2, 3, 4, 5, 6]
# 指定内容插入
l.insert(3, 100)
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6]
# 合并序列   等同于  +=
l.extend(range(1, 5))
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2, 3, 4]
# 删除
# 删除最后一个
l.pop()
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2, 3]
l.pop()
print(l, id(l))  # [1, 2, 3, 100, 4, 5, 6, 1, 2]
# 删除指定位置的元素
l.pop(2)  # 2  指的是索引
print(l, id(l))  # [1, 2, 100, 4, 5, 6, 1, 2]
# 删除指定元素   元素的值
l.remove(1)  # 1 指的是元素的值 是  1
print(l, id(l))  # [2, 100, 4, 5, 6, 1, 2]
# 清空
l.clear()
print(l, id(l))  # []

列表推导式
  • 列表中数据筛选或者转化的简化,虽然是简化,效率要比append高

  • 应用场景
    
    筛选满足条件的数据  判断是否满足  if条件
    [变量名  for 变量名 in 序列 if 判断条件]
    
    转换  每一个都转换  没有if条件 
    [变量对应的转换操作 for 变量名 in 序列]
    
排序算法【升序】

冒泡排序

  • 排序规则:

    • 每次都从下标为0的位置开始,相邻两个元素两两比较,如果前者大于后者,两个元素交换位置
    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    冒泡排序  升序
    [54, 45, 69, 39, 88, 24, 89]   --- 获取一个最大值
    [45, 54, 39, 69, 24, 88, 89]   ---  获取第二个最大值
    [45, 39, 54, 24, 69, 88, 89]   --- 获取第三个最大值
    [39, 45, 24, 54, 69, 88, 89]  --- 获取第四个最大值
    [39, 24, 45, 54, 69, 88, 89]  --- 获取第五个最大值
    [24, 39, 45, 54, 69, 88, 89]  --- 最后两个排序
    每一次 都是从下标为0开始  与后面的相邻一个元素两两比较  如果前者大于后者  两者交换位置
    重复循环几次  6次
    l中元素  总共有7个元素   循环  6次    如果l中有n个元素  循环  n-1次  每一次循环 都从0开始 和后面的元素比较
    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    for j in range(1, len(l)):
        # 每次都从下标为0开始 相邻两个元素两两比较
        for i in range(0, len(l) - j):
            # 如果前者大于后者
            if l[i] > l[i + 1]:
                # 交换位置  a,b = b,a
                l[i], l[i + 1] = l[i + 1], l[i]
    print(l)  # [24, 39, 45, 54, 69, 88, 89]
    
    
    
    

选择排序

  • 排序规则

    • 首先在未排序的序列中找到最小值,和第一个元素进行交换
    • 再在未排序的序列中找到最小值,和第二个元素进行交换
    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    第一次  先找最小值  24     [24, 54, 45, 88, 39, 89, 69]
    第二次  先找最小值  39      [24, 39, 45, 88, 54, 89, 69]
    第三次  先找最小值  45     [24, 39, 45, 88, 54, 89, 69]
    第四次  先找最小值  54      [24, 39, 45, 54, 88, 89, 69]
    第五次  先找最小值  69      [24, 39, 45, 54, 69, 89, 88]
    第六次  先找最小值  88      [24, 39, 45, 54, 69, 88, 89]
    如果列表长度有n个  需要排序的过程  n-1次
    每一次中 找到最小值  交换
    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    # 寻找的是最小值的索引
    for j in range(0, len(l) - 1):  # 循环找最小值的次数 循环找 长度-1 次就可以
        # j 表示的 最小值要放的位置
        pos = j  # 未排序中的最小值的位置
        for i in range(j + 1, len(l)):
            if l[i] < l[pos]:
                pos = i
        if j != pos:
            l[j], l[pos] = l[pos], l[j]
    print(l)
    
    
    
    

插入排序

  • 排序规则

    • 123456789 
      
       2 5  7   1
      
    • 从索引为1的位置开始,与左边的元素进行比较 如果 左边的元素 大于 右边的元素 则两者交换位置

    • 从索引为2的位置开始 与左边的元素进行比较 【两两比较】 如果 左边的元素 大于 右边的元素 则两者交换位置

    • 从索引为3开始 xxx

    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    第一次    [54, 69, 45, 88, 39, 89, 24]   -- 把前两个数 排列好
    第二次    [45, 54, 69, 88, 39, 89, 24]   --- 前3个数  排列好
    第三次    [45, 54, 69, 88, 39, 89, 24]
    第四次    [39, 45, 54, 69, 88, 89, 24]
    第五次     [39, 45, 54, 69, 88, 89, 24]
    第六次     [24, 39, 45, 54, 69, 88, 89]    排序好  升序排序
    从第二个元素开始  索引为1的位置开始
    '''
    l = [69, 54, 45, 88, 39, 89, 24]
    for i in range(1, len(l)):  # i= 1
        for j in range(i, 0, -1):
            if l[j] < l[j - 1]:
                l[j], l[j - 1] = l[j - 1], l[j]
            else:
                break  # 结束的是内层循环
    print(l)  # [24, 39, 45, 54, 69, 88, 89]
    
    
    
    

快速排序 【函数的时候】

元组

概念及特点
  • 和列表是类似的,标识是(),存储零个或者多个元素,和列表的区别在于列表是可变的,元组是不可变的
  • 应用场景:数据已经确定,不再进行改变,建议使用元组,比使用列表更省内存
  • month in (1,3,5,7,8,10,12) month in [1,3,5,7,8,10,12]
  • 特点
    • 有序

      • 有索引
    • 不可变

      • 内存地址不变的情况下,数据不会发生改变
      # 特点
      # 有序 索引和切片 和字符串 一样  不可变  字符串一样
      t = (45, 67, 89, 10, 30)
      print(t[0])
      print(t[-1])
      print(t[:])
      print(t[::-1])
      print(t[:3])
      print(t[-3:])
      # 不能修改
      # t[0] = 1000
      # print(t)   # 'tuple' object does not support item assignment
      # 不可变性  内存地址不变的情况下 内容不会发生变化
      t = (1, 2, 3, 4)
      print(t, id(t))
      t += (5, 6)
      print(t, id(t))
      
      
定义元组
  • 直接使用()包含
  • 使用tuple()构造
# 元组中有几个元素 被称为几元组
# 如果元组中只有一个元素 定义的时候 元素后面 加 逗号
t = ()
print(t, type(t), len(t))
t = tuple()
print(t, type(t), len(t))
#
t = (10,)
print(t, type(t), len(t))  # (10,) <class 'tuple'> 1

t = tuple([1, 2, 3])
print(t)
t = tuple(range(10))
print(t)
t = tuple('abc')
print(t)


元组支持的运算符
符号含义
+合并元组 产生一个新元组
*重复 产生一个新元组
+=合并元组 产生一个新元组
不能像列表 合并 列表 字符串 range
*=重复 产生一个新元组
比较相同位置逐个比较,直到比较出大小
成员数据是否为元组中的元素
t1 = (1, 2, 3)
t2 = (4, 5, 6)
print(t1 + t2)  # (1, 2, 3, 4, 5, 6)
print(t1 * 2)  # (1, 2, 3, 1, 2, 3)

# +=
print(t1, id(t1))
t1 += t2
print(t1, id(t1))
# *=
t1 *= 2
print(t1, id(t1))  
# 成员
print(6 in t1)  # True
# 比较
print(t1 > t2)  # False

元组的索引和切片
  • 和字符串是一样的 只有获取的操作
元组的遍历
  • 直接遍历元组
  • 遍历索引
  • 枚举遍历
元组的操作

获取元素出现的次数
元组对象.count(元素)

获取
获取第一次出现的位置   元组.index(元素,起始索引,结束索引)
获取出现的次数        元组.count(元素)
l = (1, 2, 3, 4, 1)
#
print(l.index(1))
print(l.count(1))

# 遍历
l = (1, 2, 3, 4, 1)
# 获取数字2的索引
for pos, ele in enumerate(l):
    if ele == 2:
        print(pos)

# 把满足条件的内容放在列表中
l1 = []
for i in l:
    if i % 2 == 0:
        l1.append(i)
print(l1)

装包和拆包

装包 – 使用逗号分隔定义多个数据,赋值给一个变量,把多个数据打包成一个元组,赋值给变量,这个过程就是装包

拆包 – 使用多个变量接受一个序列,把序列中的内容解包,将对应位置的值赋值给对应位置的变量,这个过程就是拆包

# 装包
a = 10, 20, 30
print(a, type(a))  # (10, 20, 30) <class 'tuple'>
# 拆包
t = (100, 200, 300)
a, b, c = t
print(a, b, c)  # 100 200 300

l = ['how', 'are', 'you']
for pos, ele in enumerate(l):
    print(pos, ele)  # pos 索引  ele  元素

# 拆包  注意  变量数与序列中的元素数要一致 才能解包 不然会报错
# 变量数 < 序列中的元素数  错误可解  让某一个变量 接受多个内容  让某一个变量前面加* 被*修饰过的变量接受多个值
# a,b, = (100,200,300)
# print(a,b)   # ValueError: too many values to unpack (expected 2)
a, *b, = (100, 200, 300)
print(a, b)  # 100 [200, 300]

*a, b, = (100, 200, 300)
print(a, b)  # [100, 200] 300

*a, b, c = (10, 20, 30, 40, 50, 60)
print(a, b, c)  # [10, 20, 30, 40] 50 60

a, *b, c = (10, 20, 30, 40, 50, 60)
print(a, b, c)  # 10 [20, 30, 40, 50] 60

a, b, *c = (10, 20, 30, 40, 50, 60)
print(a, b, c)  # 10 20 [30, 40, 50, 60]

# a,*b,*c = (10,20,30,40,50,60)
# print(a,b,c)

# 变量数 > 序列中的元素数
# a,b,c,d = (100,200,300)
# print(a,b)  # ValueError: not enough values to unpack (expected 4, got 3)

字典

概念及特点
  • 标识是{},数据是成对出现的,key:value的形式,称为键值对,存储零个或者多个键值对的无序可变序列

  • 无序

    • 没有索引 没有编号
    • 通过键值对中的键进行定位 ,所以对键有要求
      • 键不允许重复
      • 键的数据类型是不可变的
  • 可变

    • 内存地址不变的情况下,键值对可以发生变化 【增加、删除、修改】
    # 定义字典
    # 空字典  长度 0
    d = {}
    print(d, type(d), len(d))  # {} <class 'dict'> 0
    d = dict()
    print(d, type(d), len(d))  # {} <class 'dict'> 0
    # 非空字典
    d = {'数学': 88, '语文': 99}
    print(d, type(d), len(d))  # {'数学': 88, '语文': 99} <class 'dict'> 2
    #  函数 构造 非空字典
    # 传递 二维数据
    data = [('数学', 88), ('语文', 66)]
    d = dict(data)
    print(d, type(d), len(d))  # {'数学': 88, '语文': 66} <class 'dict'> 2
    # 传递  变量名=值  变量名 没有引号
    d = dict(英语=77, 化学=66)
    print(d, type(d), len(d))  # {'英语': 77, '化学': 66} <class 'dict'> 2
    
    # 特点  无序  可变
    d = {'英语': 77, '化学': 66}
    # print(d[0])  # KeyError: 0
    # 字典 通过键进行定位键值对  对键有要求   键不能重复   键是不可变数据类型
    d = {'英语': 77, '英语': 66}
    print(d)    # {'英语': 66}
    # d = {[10,20]:99}
    # print(d,type(d))    # TypeError: unhashable type: 'list'
    # 可变   内存地址不变的情况  修改数据
    d = {'英语': 77, '化学': 66}
    print(d,id(d))    # {'英语': 77, '化学': 66}
    # 新增键值对   字典[键] = 值
    d['数学'] = 100
    print(d,id(d))  # {'英语': 77, '化学': 66, '数学': 100}
    
    
    
    
定义字典
  • 使用{}包含 ,数据的格式 key:value
  • 使用dict()构造
字典支持的运算符
  • 成员运算符 判断数据是否在字典的键中
d1 = {'英语': 77, '化学': 66}
d2 = {'数学': 88, '语文': 99}
# 成员 判断的是数据是否在字典的键中
print('化学' in d1)   # True
print(77 in d1)   # False








字典的操作
增
	添加键值对
		字典对象[键] = 值
			键存在	    将新值覆盖原有键对应的值 【修改】
			键不存在   添加键值对 
删
	删除键值对
		字典对象.pop(键)
			键存在  把对应的键值对删除
			键不存在  报错  
改
	修改某个键对应的值
		字典对象[键] = 值
			键存在	    将新值覆盖原有键对应的值 【修改】
获取
	获取某个键对应的值
		字典对象[键]
			键存在 获取对应的值
			键不存在 报错 
		字典对象.get(键)
			键存在 获取对应的值
			键不存在 返回None			
	获取字典中所有的键
		字典对象.keys()	
	获取字典中所有的值
		字典对象.values()
    获取字典中所有的键值对  返回的 二维数据 
    	字典对象.items()
	
d1 = {'英语': 77, '化学': 66}
print(d1, id(d1))  # {'英语': 77, '化学': 66}
# 增加键值对
# 字典[键] = 值
d1['数学'] = 88
print(d1, id(d1))  # {'英语': 77, '化学': 66, '数学': 88}
# 如果键存在  修改
d1['化学'] = 100
print(d1, id(d1))  # {'英语': 77, '化学': 100, '数学': 88}
# 字典.setdefault(键,值)
d1.setdefault('语文', 80)
print(d1, id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80}
d1.setdefault('数学', 100)
print(d1, id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80}
# 合并序列  字典.update()
d1.update({'音乐': 100, '体育': 30})
print(d1, id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80, '音乐': 100, '体育': 30}
d1.update([('生物', 90), ('物理', 76)])
print(d1, id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80, '音乐': 100, '体育': 30, '生物': 90, '物理': 76}
d1.update(历史=95, 政治=99)
print(d1,
      id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80, '音乐': 100, '体育': 30, '生物': 90, '物理': 76, '历史': 95, '政治': 99}

# 删除键值对
del d1['体育']
print(d1,id(d1))  # {'英语': 77, '化学': 100, '数学': 88, '语文': 80, '音乐': 100, '生物': 90, '物理': 76, '历史': 95, '政治': 99}
d1.pop('音乐')
print(d1,id(d1))   # {'英语': 77, '化学': 100, '数学': 88, '语文': 80, '生物': 90, '物理': 76, '历史': 95, '政治': 99}
# d1.clear()
# print(d1,id(d1))   # {}
# 修改的操作  获取再赋值
d1['化学'] = 40
print(d1,id(d1))    # {'英语': 77, '化学': 40, '数学': 88, '语文': 80, '生物': 90, '物理': 76, '历史': 95, '政治': 99}
# 获取的操作
# 获取某个键对应的值    只有 值
print(d1['语文'])  # 80
# print(d1['文文'])    # KeyError: '文文'
print(d1.get('语文'))  # 80
print(d1.get('文文'))  # None
print(d1.get('文文',0))  # 0
# 获取字典中所有的键 可遍历
print(d1.keys())   # dict_keys(['英语', '化学', '数学', '语文', '生物', '物理', '历史', '政治'])
# 获取字典中所有的值
print(d1.values())   # dict_values([77, 40, 88, 80, 90, 76, 95, 99])
# 获取字典所有的键值对
print(d1.items())   # dict_items([('英语', 77), ('化学', 40), ('数学', 88), ('语文', 80), ('生物', 90), ('物理', 76), ('历史', 95), ('政治', 99)])
# 复制  产生一个新的
print(d1.copy())   # {'英语': 77, '化学': 40, '数学': 88, '语文': 80, '生物': 90, '物理': 76, '历史': 95, '政治': 99}
# 根据键序列构造字典  快速构建字典的方式
# 构建一个字典  键  数学  语文 英语
d = dict.fromkeys(['数学','语文','英语'])
print(d)   # {'数学': None, '语文': None, '英语': None}
# 如果指定的值为不可变数据类型,修改其中的某个值,其他值不会变化
d = dict.fromkeys(['数学','语文','英语'],88)
print(d)   # {'数学': 88, '语文': 88, '英语': 88}
# 修改数学成绩为100
d['数学'] = 100
print(d)   # {'数学': 100, '语文': 88, '英语': 88}
# 如果指定的值为可变数据类型,修改其中的某个值,所有的都跟着变化
d = dict.fromkeys(['数学','语文','英语'],[])
print(d)   # {'数学': [], '语文': [], '英语': []}
# 字典中 数学键对应的列表中 添加数据 4
d['数学'].append(4)
print(d)  # {'数学': [4], '语文': [4], '英语': [4]}
print(id(d['数学']))
print(id(d['语文']))
print(id(d['英语']))










字典的遍历
  • 直接遍历字典 【遍历的是字典的键】
  • 遍历字典所有的键 【字典.keys()】
  • 遍历字典的值 【字典.values()】
  • 遍历字典的键值对 【字典.items()】
d = {'数学': 98, '语文': 95, '英语': 53, '化学': 75}
# 直接遍历字典  遍历字典的键
# for i in d:
#     print(i)
# # 遍历字典的键
# for i in d.keys():
#     print(i)

# 获取成绩及格的科目
# 只要科目
# for i in d:
#     # i 字典的键  成绩 值   获取字典中某个键对应的值
#     if d[i] >= 60:
#         print(i)
d = {'数学': 98, '语文': 95, '英语': 53, '化学': 75}
# 科目和对应的成绩   {'数学': 98, '语文': 95,  '化学': 75}
d1 = {}
for i in d:
    # i 字典的键
    if d[i] >= 60:
        # 把键值对 添加到 d1 中  键  i    值  d[i]
        d1[i] = d[i]
print(d1)
# 遍历键值对
print(d.items())  # dict_items([('数学', 98), ('语文', 95), ('英语', 53), ('化学', 75)])
for i in d.items():
    # i 元组  元组中有两个元素  第一个 是键  第二个 值
    print(i)
for k, v in d.items():
    print(k, v)  # k 接受的是 键   v  接受的是 值
# 遍历键值对
d1 = {}
for k, v in d.items():
    if v >= 60:
        d1[k] = v
print(d1)
# 获取字典中成绩为偶数的 科目与成绩
d2 = {}
for k, v in d.items():
    if v % 2 == 0:
        d2[k] = v
print(d2)
# 获取字典中成绩在80以下的 科目与成绩
d3 = {}
for k, v in d.items():
    if v < 80:
        d3[k] = v
print(d3)
# 获取字典中成绩在70-90之间的科目 存储在列表中
l = []
for k, v in d.items():
    if 70 <= v <= 90:
        l.append(k)
print(l)
# 列表推导式
print([k for k, v in d.items() if 70 <= v <= 90])

字典推导式

类似于列表推导式

结构 {键的变量:值的变量 for 键的变量,值的变量 in 序列 if 条件语句}

{k:v  for k,v  in 字典.items()  if 条件}
d = {'数学': 98, '语文': 95, '英语': 53, '化学': 75}
# 获取成绩及格的科目与对应成绩
# 字典推导式
print({k: v for k, v in d.items() if v >= 60})
# 成绩偶数
print({k: v for k, v in d.items() if v % 2 == 0})
# 80以下
print({k: v for k, v in d.items() if v < 80})

d = {'数学': 98, '语文': 95, '英语': 53, '化学': 75}
# 键值互换
# d = {98:'数学',95:'语文'}
print({v: k for k, v in d.items()})

# 字典的应用
import string
from collections import Counter

# 词频统计
s = 'djhgajdhsgfhjadgfhadgfaf'
# 统计s中每一个字符 出现的次数  {'d':5,'j':5,'h':3,'g':2}
d = {}
for i in s:
    # i 表示的是字符串中每一个数据   键
    # 值  i的个数
    # 在s中数 i的次数  字符串的操作
    c = s.count(i)
    # 添加键值对
    d[i] = c
print(d)
# Counter
# 获取词频统计
print(Counter(s))
# 获取统计后的前几名
print(Counter(s).most_common(5))  # [('d', 4), ('h', 4), ('g', 4), ('a', 4), ('f', 4)]

s = 'you are very cool you are very good good good study'
# 统计 单词的个数   产生单词的概念  字符串的切割
l = s.split()
print(l)  # ['you', 'are', 'very', 'cool', 'you', 'are', 'very', 'good', 'good', 'good', 'study']
d = {}
for i in l:
    c = l.count(i)
    # 字典中添加键值对
    d[i] = c
print(d)

print(Counter(l))

s = 'djhHGF557gYF'
# 统计s中大写字母 小写 数字的个数  形成一个字典  {'大写':5,'小写':6}
# d = {'大写': 0, '小写': 0, '数字': 0}
d = dict.fromkeys(['大写', '小写', '数字'], 0)
for i in s:
    if i in string.ascii_uppercase:
        d['大写'] += 1
    elif i in string.ascii_lowercase:
        d['小写'] += 1
    elif i in string.digits:
        d['数字'] += 1
print(d)

scores = {'语文': 88, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56}
# 统计 及格科目 与不及格科目的个数
d = dict.fromkeys(['及格', '不及格'], 0)
print(d)  # {'及格': 0, '不及格': 0}
for i in scores:
    if scores[i] >= 60:
        d['及格'] += 1
    else:
        d['不及格'] += 1
print(d)

d = dict.fromkeys(['及格', '不及格'], 0)
print(d)  # {'及格': 0, '不及格': 0}
for k, v in scores.items():
    if v >= 60:
        d['及格'] += 1
    else:
        d['不及格'] += 1
print(d)

d = dict.fromkeys(['及格', '不及格'], 0)
print(d)  # {'及格': 0, '不及格': 0}
for i in scores.values():
    if i >= 60:
        d['及格'] += 1
    else:
        d['不及格'] += 1
print(d)

scores = {'语文': 88, '数学': 97, '英语': 28, '政治': 77, '历史': 65, '化学': 78, '生物': 77, '地理': 56}
# 获取 及格的科目有哪些  不及格的科目有哪些  {'及格': [], '不及格': []}
d = {'及格': [], '不及格': []}
# d = dict.fromkeys(['及格','不及格'],[])  # 为什么??其中一个修改  所有的都跟着修改
for k, v in scores.items():
    if v >= 60:
        d['及格'].append(k)
    else:
        d['不及格'].append(k)
print(d)

nums = [27, 39, 41, 28, 56, 53, 48, 22]
# 获取偶数 有哪些  奇数有哪些  形式为字典
d = {'偶数': [], '奇数': []}
for i in nums:
    if i % 2 == 0:
        d['偶数'].append(i)
    else:
        d['奇数'].append(i)
print(d)

列表与字典的结合

'''
班级中有多个学生  每个学生 多个特点  姓名  年龄  性别  成绩
[{'姓名':'小明','年龄':15,'性别’:'男','成绩':88},
{'姓名':'小红','年龄':15,'性别’:'男','成绩':88},
{'姓名':'小美','年龄':15,'性别’:'男','成绩':88},
{'姓名':'小强','年龄':15,'性别’:'男','成绩':88}]
'''
students = [
    {'学号': 1, '姓名': '乐乐', '年龄': 12, '性别': '男', '成绩': 71},
    {'学号': 2, '姓名': '倩倩', '年龄': 11, '性别': '女', '成绩': 83},
    {'学号': 3, '姓名': '苗苗', '年龄': 13, '性别': '女', '成绩': 98},
    {'学号': 4, '姓名': '旭旭', '年龄': 12, '性别': '男', '成绩': 65},
    {'学号': 5, '姓名': '花花', '年龄': 11, '性别': '男', '成绩': 66}
]
# print(type(students))
# for i in students:
#     print(i)

# 获取 students中 成绩为偶数的 学生信息   产生结果列表 列表中存储满足条件的学生信息【字典】
l = []
for i in students:
    # i  字典  判断是的成绩 是否为偶数   字典[键]
    if i['成绩'] % 2 == 0:
        l.append(i)
print(l)
# 使用列表推导式
print([stu for stu in students if stu['成绩'] % 2 == 0])
# 获取所有性别为男的学生信息
# 列表推导式
print([stu for stu in students if stu['性别'] == '男'])

# 对列表进行排序  按照学生的成绩  升序排序
# 冒泡
for i in range(1, len(students)):
    for j in range(0, len(students) - i):
        # 判断 时候  学生的成绩  前者大于后者  交换
        if students[j]['成绩'] > students[j + 1]['成绩']:
            # 交换  成绩  学生
            students[j], students[j + 1] = students[j + 1], students[j]
print(students)



集合

概念及特点

概念:存储不重复元素的 无序可变的 序列 【去重】

特点:无序 : 没有索引和切片

​ 可变: 内存地址不变的情况下 ,数据可以发生变化 增加 删除

​ 唯一性:数据是 唯一的

定义集合

使用{}包含 不能用来定义空集合 数据不能是键值对形式

使用 set() 函数构造

# 定义
# 空集合
s = set()
print(s, type(s), len(s))  # set() <class 'set'> 0
s = {}
print(s, type(s), len(s))  # {} <class 'dict'> 0
# 非空集合
s = {1, 2, 3}
print(s, type(s), len(s))  # {1, 2, 3} <class 'set'> 3
s = {1, 2, 3, 1, 2, 3}
print(s, type(s), len(s))  # {1, 2, 3} <class 'set'> 3
s = set('aaabbbccc')
print(s, type(s), len(s))  # {'b', 'c', 'a'} <class 'set'> 3
s = {'b', 'c', 'a'}
print(''.join(s))  # 'cba'
# 特点   唯一性  不重复
s = {1, 2, 3, 4}
print(s, id(s))
# print(s[0])
# 可变    内存地址不变情况  增加元素  删除元素
s.add(5)
print(s, id(s))


支持的运算符
子集 是部分或者全部      真子集  只能是部分
s = {1,2,3,4} 
{3,4} 是 s的子集 
{3,4} 是 s的真子集 

{1,3,4,2}是s的子集 
{1,2,3,4}不是s的真子集
符号含义
&两个集合的交集 左边集合存在 右边集合也存在
|两个集合的并集 左边集合存在 或者 右边集合存在
^对称差集 并集 去掉 交集部分
-差集 a - b 指 在集合a中去除掉 与b共有的部分 b - a 在集合b中去除 与a共有的
&=不产生新集合
|=不产生新集合
^=不产生新集合
-=不产生新集合
>判断 右边集合是否为左边集合的真子集
>=判断 右边集合是否为左边集合的子集
<判断 左边集合是否为右边集合的真子集
<=判断 左边集合是否为右边集合的子集
==判断两个集合中的内容是否一样 与顺序无关 {1,2,3} == {3,1,2}
!=判断两个集合中的内容是否不一样
in
not in
s1 = {1, 2, 3}
s2 = {3, 4, 5}
# &
print(s1 & s2)  # {3}
# |
print(s1 | s2)  # {1, 2, 3, 4, 5}
# ^   并集 -  交集
print(s1 ^ s2)  # {1, 2, 4, 5}
# -   a-b  b-a
print(s1 - s2)  # {1, 2}
print(s2 - s1)  # {4, 5}
# 在左边集合的基础上做变化 不产生新集合
s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1, id(s1))
# &=
s1 &= s2
print(s1, id(s1))  # {3}
# |=
s1 |= s2  # {3}  {3,4,5}
print(s1, id(s1))  # {3, 4, 5}
# ^=
s1 ^= s2  # s1  {3, 4, 5}    s2  {3, 4, 5}
print(s1, id(s1))  # set()
# -=
s1 -= s2  # s1  set()   s2  {3, 4, 5}
print(s1, id(s1))  # set()
# 比较
s1 = {1, 2, 3}
s2 = {3, 2, 1}
s3 = {2,1}
print(s2 < s1)
print(s2 <= s1)
print(s1>s3)
print(s1>=s2)
print(s1==s2)
# 成员
print(1 in s1)
print(3 in s3)



集合的遍历

直接遍历集合

集合的操作
可变  

增加  
	集合.add(元素)  如果元素不存在 则添加  如果集合中元素存在  不做反应
删除  
	集合.remove(元素)  如果元素存在 则删除 如果元素不存在  报错 
	集合.discard(元素)  如果元素存在 则删除 如果元素不存在 不做反应  
	集合.clear()   清空
其他 
	复制  集合.copy()  
s = {1, 2, 3}
print(s, id(s))
# 增加
s.add(4)
print(s, id(s))  # {1, 2, 3, 4}
s.add(1)
print(s, id(s))  # {1, 2, 3, 4}
# 删除
s.remove(1)
print(s, id(s))  # {2, 3, 4}
# s.remove(5)
# print(s,id(s))   # KeyError: 5
s.discard(2)
print(s, id(s))  # {3, 4}
s.discard(5)
print(s, id(s))  # {3, 4}
s.clear()
print(s, id(s))  # set()
print(s.copy())  # set()

# 集合的应用
# 已知学习语文的人有小红,小明,小刚,乐乐,焕焕;学习数学的人有小刚,乐乐,倩倩,茜茜;学习英语的人有乐乐,倩倩,露露,莎莎。
chinese = {'小红', '小明', '小刚', '乐乐', '焕焕'}
math = {'小刚', '乐乐', '倩倩', '茜茜'}
english = {'乐乐', '倩倩', '露露', '莎莎'}
# 3. 三科都学的有几个,分别是谁
print(chinese & math & english)   # {'乐乐'}
# 2. 同时学习了语文和数学的有几个,分别是谁
print(chinese & math)
# 1. 只学习了语文的人有几个,分别是谁
print(chinese - math - english)


深浅拷贝

拷贝:列表 字典 集合 可变序列 拷贝就是复制一份新的 ,

深浅拷贝 针对于二维及以上数据来说,深浅拷贝 对于外层一定是复制了一份新的,区别在与内层是否复制新的

模块 import copy

浅拷贝:只外层产生新的,内层地址使用的是原来的 copy.copy()

深拷贝:内外都是新的 copy.deepcopy()

import copy  # 拷贝模块

# 深浅拷贝
l = [[1, 2, 3], [4, 5, 6]]
print(id(l), id(l[0]), id(l[1]))  # 2638337544448 2638337486208 2638335345152
# 浅拷贝   只有外层是新的  里层使用的是原来的
copy_copy = copy.copy(l)
print(id(copy_copy), id(copy_copy[0]), id(copy_copy[1]))  # 2638337544384 2638337486208 2638335345152
# 深拷贝  内外都是新的
deep_copy = copy.deepcopy(l)
print(id(deep_copy), id(deep_copy[0]), id(deep_copy[1]))  # 2638337544512 2638337544576 2638336390720
# 深浅拷贝
l = [[1, 2, 3], [4, 5, 6]]
# 浅拷贝
copy_copy = copy.copy(l)
# print(copy_copy)
# 深拷贝
deep_copy = copy.deepcopy(l)         
# print(deep_copy)
l.append([7, 8, 9])
print(l)  # [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(copy_copy)  # [[1, 2, 3], [4, 5, 6]]
print(deep_copy)  # [[1, 2, 3], [4, 5, 6]]
# 如果 在内层中 修改
l[0].append(1000)
print(l)  # [[1, 2, 3, 1000], [4, 5, 6], [7, 8, 9]]
print(copy_copy)  # [[1, 2, 3, 1000], [4, 5, 6]]
print(deep_copy)  # [[1, 2, 3], [4, 5, 6]]

copy_copy[1].append(2000)
print(copy_copy)  # [[1, 2, 3, 1000], [4, 5, 6,2000]]
print(l)  # [[1, 2, 3, 1000], [4, 5, 6,2000], [7, 8, 9]]
print(deep_copy)  # # [[1, 2, 3], [4, 5, 6]]

函数

函数的定义

函数的应用场景:某些代码会被重复使用,为了避免代码的重复性,把重复性的内容封装成函数,在需要的地方进行调用

函数的语法结构

定义函数的语法结构
def 函数名(形式参数1,形式参数2):
	函数的功能体  
	return 函数的返回结果  

def -- 定义函数的关键字 
函数名 -- 满足命名规范 多个单词使用下划线隔开 
() -- 必须写 存放形式参数[形参] ,未知数,变量名  
	求两个数的和    未知数  两个数  
	求某年某月的天数  未知数   年  月 
    打印九九乘法表   没有未知数   
函数的功能体  --- 函数实现的是什么功能 
return  应用在函数中的关键字  作用   结束函数  并把返回结果返回到调用位置 
	也不是必须有 可以没有  
	如果没有ruturn  相当于 返回 return None 

调用函数 
函数名(实际参数1,实际参数2)

实际参数 简称 实参  调用函数传递的实际的值
实参也不是必须有    可能没有  如果定义函数没有形参 不需要实参   
# 求两个数的和   未知数  两个数   两个变量  表示 两个数   函数的功能体  求和
def get_sum(num1, num2):
    # 函数体
    res = num1 + num2
    # 返回值   结束函数  并把 返回结果返回到调用位置
    return res


# 调用函数
a = get_sum(10, 20)
print(a)  # 30
print(get_sum(10, 5))
print(get_sum(5, 6))
print(get_sum(10, 2))
print(get_sum(60, 70))
print(get_sum(50, 60))


# 封装一个函数 获取两个数中的最大值  未知数  两个数  函数的功能体  获取最大值
def get_max(num1, num2):
    # 函数体  函数实现的功能  已知num1 num2 获取最大值
    # if num1>num2:
    #     return num1
    # else:
    #     return num2
    # 三元         表达式1    if  条件 esle 表达式2
    return num1 if num1 > num2 else num2


# 调用
print(get_max(10, 5))
print(get_max(100, 200))
print(get_max(50, 60))


# 封装一个函数判断某年是否为闰年 未知数  年   函数的功能体  判断给的年份是否为闰年
def is_leap(year):
    # if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
    #     return True
    # else:
    #     return False
    return True if year % 4 == 0 and year % 100 != 0 or year % 400 == 0 else False


print(is_leap(2000))
print(is_leap(2023))
print(is_leap(2004))


# 封装一个函数 获取 1到某个数的 和   键盘输入一个数 获取1-这个数的和   未知数  一个  某个数  函数的功能体  1+2+3+4.。。。+某个数
def get_all_sum(num):
    res = 0
    for i in range(1, num + 1):
        res += i
    return res


print(get_all_sum(100))  # 5050
print(get_all_sum(10))  # 55
print(get_all_sum(1000))  # 500500
print(get_all_sum(10000))  # 50005000



# 封装九九乘法表   没有形参   没有未知量   没有return    作用  结束函数 并把函数的返回值返回到调用位置
def get_table():
    # 函数的功能体
    for i in range(1,10):
        for j in range(1,i+1):
            print(f'{j}*{i}={i*j}',end='\t')
        print()
    return None

get_table()
get_table()
get_table()

# 封装九九乘法表  打印指定行数的九九乘法表  形参 行数
def get_table1(line):
    # 函数的功能体
    for i in range(1,line+1):
        for j in range(1,i+1):
            print(f'{j}*{i}={i*j}',end='\t')
        print()

get_table1(4)
get_table1(6)
get_table1(3)
函数的执行流程

定义出来函数,函数体不会被执行

调用函数的时候,才会执行函数体

# 定义函数       函数体不会被执行
# def haha():
#     res = 1/0
#     return res

# 调用函数执行函数体
# print(haha())

# 判断是否为闰年
def is_leap(year):
    if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
        return True
    else:
        return False
    # return True if year % 4 == 0 and year % 100 != 0 or year % 400 == 0 else False


# 封装一个函数  获取某年某月的天数   未知数  年  月   函数的功能体  求天数
def get_days(year, month):
    if month in (1, 3, 5, 7, 8, 10, 12):
        return 31
    elif month in (4, 6, 9, 11):
        return 30
    else:
        return 29 if is_leap(year) else 28


print(get_days(2023, 2))

全局变量与局部变量

全局变量:直接定义在python文件中的变量,能够在任意位置【可以在函数中 可以在函数外面】被访问

局部变量:函数有自己独立的作用域中,函数中定义的变量称为局部变量

函数中使用变量,首先会检查自己的域中,有没有这个变量,如果有使用自己域中变量,如果没有,扩大范围到全局中查找,如果全局中有这个变量,使用全局的,如果全局中没有则报错

如果函数内,想要修改全局变量,需要一个修饰符修饰变量,global 作用:告诉解释器 变量来源于全局

# 全局变量
# age = 18
# def show_age():
    # 函数体内  没有age变量  实际上使用的是 全局的 age = 18
    # print(age)   #  18

    # 局部变量
    # age = 10
    # age 实际上的 局部变量  age
    # print(age)   # 10

    # 全局age 注释了
    # print(age)   # NameError: name 'age' is not defined
# show_age()

# def show_age():
#     # 局部变量  只能函数中使用  出了函数不能使用
#     age = 10
#
# print(age)   # NameError: name 'age' is not defined

# 全局变量 age
age = 18
def show_age():
    # 告诉解释器 age来源于全局的
    global age
    # 不是定义了一个局部变量age  而是修改了全局变量age
    age = 10
    # 局部变量age
    print(age)
show_age()
# 打印的全局的age
print(age)



函数的参数
位置参数【必要参数】

定义函数时设置的形参,没有特殊标记都是位置参数

调用函数的时候,位置参数必须传值,值和参数要一一对应

默认参数

定义函数的时候,给参数了默认值,在大多数场景下都符合 print(*args,sep=' ')

默认参数可以不进行传值,不传值,使用的就是默认值

如果传值,使用的就是新值

注意:默认参数的定义在位置参数之后

关键字参数

调用函数的时候,可以使用变量名=值的形式进行传值,如果使用了变量名=值的形式传值,那顺序可以与定义的顺序不一样

注意:关键字参数传值要在位置参数传值之后

命名式关键字参数 :必须使用关键字参数传值

格式 形参1,参数2,*,形参3,形参4 *后面的参数必须使用关键字参数传值

可变参数

形参的个数不确定

因为函数调用传值有位置参数传值和关键字参数传值两种

可变参数有两种形式

*args  *a  *b 
	接受的是位置参数传值  把传值的内容打包成一个元组 
	args -- 元组    空元组 

**kwargs   **m   **n 
	接受的是关键字参数传值  把传值的内容打包成一个字典 
	kwargs -- 字典   空字典  
	
# 获取某年某月的天数

def is_leap(year):
    if year % 4 == 0 and year % 100 != 0 or year % 400 == 0:
        return True
    else:
        return False
    # return True if year % 4 == 0 and year % 100 != 0 or year % 400 == 0 else False


# 封装一个函数  获取某年某月的天数   未知数  年  月   函数的功能体  求天数
def get_days(year, month):
    if month in (1, 3, 5, 7, 8, 10, 12):
        return 31
    elif month in (4, 6, 9, 11):
        return 30
    else:
        return 29 if is_leap(year) else 28


# 位置参数
print(get_days(2000, 2))
# 关键字参数  变量名 = 值
print(get_days(month=2, year=2000))
print(get_days(2000, month=4))


# print(get_days(month=5, 2000))   # SyntaxError: positional argument follows keyword argument

# 默认参数   求一个数的 n次幂  大多数 平方
def my_power(num, n=2):
    return num ** n


print(my_power(5))  # 25
print(my_power(5, 3))  # 125
print(my_power(5, n=5))
print(my_power(num=3, n=5))
print(my_power(n=4, num=2))  # 16


def get_sum(a, b, c, d):
    return a + b + c + d


print(get_sum(1, 2, 3, 4))
print(get_sum(a=1, b=2, c=3, d=4))


def get_sum1(a, b, *, c, d):
    return a + b + c + d


print(get_sum1(1, b=2, c=3, d=4))


# 可变参数
# 求多个数的和  没有固定的个数  使用可变参数
def get_sum(*args, **kwargs):
    # print(args,type(args))   # (1, 2, 3, 4, 5)   <class 'tuple'>
    # print(kwargs,type(kwargs))   # {'a': 6, 'b': 7}   <class 'dict'>
    # args 元组  kwargs 字典 需要的是字典中值
    all_data = args + tuple(kwargs.values())  # 获取所有的数据
    # print(all_data)
    res = 0
    for i in all_data:
        res += i
    return res


print(get_sum(1, 2, 3, 4, 5, a=6, b=7))
print(get_sum(1, 2, 3, 4, 5, 10, 20, 30, a=6, b=7))
print(get_sum(1, 2, 3, 4))
print(get_sum(a=10, b=20, c=30))
print(get_sum(a=10, b=20))


# 获取多个数据的平均数  封装函数
def get_avg(*args, **kwargs):
    all_data = args + tuple(kwargs.values())
    res = 0
    for i in all_data:
        res += i
    return res / len(all_data)


print(get_avg(1, 2, 3, 4, 5))
print(get_avg(1, 2, 3, 4, 5, a=10, b=20))
print(get_avg(1, 2, 3, 4, 5, 10, 20, a=10, b=20))
print(get_avg(1, 2))

内置函数

直接可以用来使用

# 关于数学类
# 求幂数
print(pow(5, 3))   # 125
# 求绝对值
print(abs(-5))    # 5
# 四舍五入  默认保留整数
print(round(1.678))  # 2
# 保留小数位数
print(round(1.678, 2))  # 1.68
# 取整取余  //  %
print(divmod(10, 3))   # (3, 1)
# 求和
print(sum(range(1, 101)))   # 5050
print(sum([1, 2, 3, 4]))   # 10
# 求最大
print(max(10, 20, 30, 40))   # 40
print(max([10, 6, 8, 3]))    # 10
# 求最小
print(min(10, 20, 30, 40))    # 10
print(min([10, 6, 8, 3]))   # 3

# 输入输出
# print()
# input()

# 关于数据类型转换 Int()  float()  str()   list()  tuple()  set()   dict()

# 数据类型  type()

# 内存地址  id()

# 关于进制转换
# 转换为二进制
print(bin(10))   # 0b1010
# 转换为八进制
print(oct(10))   # 0o12
# 转化为十六进制
print(hex(10))   # 0xa

# 判断数据是否为指定数据类型
print(isinstance(10, int))   # True
print(isinstance('abc', str))   # True
print(isinstance([1, 2, 3], list))   # True
# 区别在于 isinstance 可以判断数据是否为 父类
# bool 继承自 int
print(isinstance(True,int))   # True
print(type(10) == int)
print(type(True) == int)    # False

# 解析字符串 eval()  和 str() 相反
print(eval('1+2+3+4'))   # 10
print(1+2+3+4)  # 10

# 文件操作  open(文件路径,打开模式,编码方式)

# 文件路径  建议使用的是相对路径
#     绝对路径  指文件在硬盘的真实位置  win  盘符开始    C:\Users\86166\Documents\上课资料\分享
#     相对路径  表示的是一个相对位置 相对于当前操作的文件来说的
#     表示符号  . 表示当前操作文件所在的目录【文件夹】   .. 表示 当前操作文件所在目录的上一级目录 【包含关系】

# 打开模式
#     写   a -- 追加写 【原有文件内容的后面追加写入】
#          w -- 清空写 【原有文件的内容删除情况 写入新内容】  字节相关 ab  wb  rb
#         如果文件路径不存在  创建一个新文件
#     读   r -- read    如果文件路径不存在  报错

# 编码方式  如果打开模式是字节类型  不需要指定编码方式







递归算法

函数中自己调用自己 ,这种形式就是递归

递归 - 一定是有规律的,并且一定是有出口的 【基例】 – 已知项

兔子  -- 1  1  2  3  5  8  13  21  34 
从第三项开始 = 前两项的和  
F(n) = F(n-1) + F(n-2)
已知项  F(1) = F(2) = 1

缺点:递归的深度不能过深,运行速度慢

# 兔子序列
# F(1)= F(2) = 1   F(n) = F(n-1) + F(n-2)
# 求某个月的兔子
def get_rabbit(month):
    # 已知项
    if month == 1 or month == 2:
        return 1
    # 规律
    else:
        return get_rabbit(month - 1) + get_rabbit(month - 2)


# print(get_rabbit(1))
# print(get_rabbit(2))
# print(get_rabbit(3))
print(get_rabbit(4))


# print(get_rabbit(5))
# print(get_rabbit(6))

# 递归求 一个数阶乘   已知项  1!=1
# N   n * (N-1的阶乘)
# 6   6*5*4*3*2*1
# 5   5*4*3*2*1
#  4  4*3*2*1
def get_fac(num):
    if num == 1:
        return 1
    else:
        return num * get_fac(num - 1)

print(get_fac(10))

# 10个人  比前面的人大3岁
# 第一个人是10岁  问第10个人多少岁
# 规律  第n个人的年龄 =  第 n-1 个人的年龄  +3   F(n) = F(n-1) +3
# 已知项  第一个人是 10
def get_age(n):
    if n == 1:
        return 10
    else:
        return get_age(n - 1) + 3

print(get_age(10))

文件操作
# 文件操作  open(文件路径,打开模式,编码方式)

# 文件路径  建议使用的是相对路径
#     绝对路径  指文件在硬盘的真实位置  win  盘符开始    C:\Users\86166\Documents\上课资料\分享
#     相对路径  表示的是一个相对位置 相对于当前操作的文件来说的
#     表示符号  . 表示当前操作文件所在的目录【文件夹】   .. 表示 当前操作文件所在目录的上一级目录 【包含关系】

# 打开模式
#     写   a -- 追加写 【原有文件内容的后面追加写入】
#          w -- 清空写 【原有文件的内容删除情况 写入新内容】  字节相关 ab  wb  rb
#         如果文件路径不存在  创建一个新文件
#     读   r -- read    如果文件路径不存在  报错

# 编码方式  如果打开模式是字节类型  不需要指定编码方式

# 打开文件 建立资源通道  写的方式打开 文件路径不存在  自动创建
fp = open('./静夜思.txt', 'w', encoding='utf-8')
# 写入内容
fp.write('''
              静夜思
                李白
        床前明月光,疑是地上霜;
        举头望明月,低头思故乡。''')
# 关闭通道 释放资源
fp.close()

# 读取内容
# 打开文件
fp = open('静夜思.txt', 'r', encoding='utf-8')
# 读取
data = fp.read()
print(data)
# 关闭
fp.close()

# ab  wb  rb  和字节相关  读取图片的数据  二进制数据   视频  音频   注意 不需要指定编码方式
# 读 背景图 的数据
# 打开图片  创建资源通道   rb
fp = open('背景图.jpeg', 'rb')
# 读取数据
img_data = fp.read()
print(img_data)
# 关闭
fp.close()

# 保存一张图片  实际上保存的图片的字节数据   把字节数据写入文件
# 打开文件
fp = open('./新背景图.jpeg', 'wb')
# 写入内容
fp.write(img_data)
# 关闭通道
fp.close()

# 上下文管理语句   打开文件  自动关闭
with open('静夜思.txt','r',encoding='utf-8') as fp:
    data = fp.read()
    print(data)

# zip()  组合函数  把多个序列相同位置的元素组合在一起
a = zip([1, 2, 3], 'abc')

for i in a:
    print(i)

print(list(zip([1, 2, 3], 'abc')))   # [(1, 'a'), (2, 'b'), (3, 'c')]

print(list(zip('abcde', [1, 2, 3])))   #  [('a', 1), ('b', 2), ('c', 3)]
















快速排序

排序规则:

  • 选定一个基准值,把数据分成两部分,一部分是比基准值大的,一部分是比基准值小的,小的在基准值左边,大的在基准值右边
  • 重复操作,在比基准值小的中,再选取基准值,把数据分成两部分,一部分是比基准值大的,一部分是比基准值小的,小的在基准值左边,大的在基准值右边
  • 重复操作
[10,20,15]
基准值  10 
  10 [20,15] 
  10 15	20 

'''
[10,5,20,18,30]
第一次    [5]  +  [基础值 10]  +  [20,18,30]
         [5]  +  [基础值 10]  +   [18] + [基准值 20] + [30]   [5,10,18,20,30]
规律 重复  选基准值  分类
出口   列表中元素 <2   元素 1  没有元素 空列表
'''
def quick_sort(l):
    # 已知项  出口
    if len(l) < 2:
        return l
    else:
        base_num = l[0]
        big_num = []
        small_num = []
        for i in l[1:]:
            if i > base_num:
                big_num.append(i)
            else:
                small_num.append(i)
        return quick_sort(small_num) + [base_num] + quick_sort(big_num)
print(quick_sort([10, 5, 18, 20, 16]))

函数的传递
def my_add(num1,num2):
    return num1+num2

print(my_add(10, 20))
print(my_add)   # <function my_add at 0x000001C697E37EE0>

# my_add 的地址 给了  f  那f 就具有了 my_add 的功能   f也能求和
f = my_add
print(f)     # <function my_add at 0x000001D090947EE0>

print(f(10, 20))








匿名函数

由关键字lambda定义的函数 ,不需要函数名,对于简单功能的封装

lambda 参数1,参数2:表达式

解读:参数1,参数2 表示的形参 表达式 表达的是返回值

求两个数的和 lambda num1,num2:num1+num2

主要应用场景:作为另外一个函数的参数进行传递

# 求两个数的和
f = lambda x, y: x + y
print(f)  # <function <lambda> at 0x000002B56B5B7EE0>
print(f(10, 20))  # 30
print(f(30, 50))
print(f(10, 5))

# 获取一个数的个位数  未知量 一个  功能  返回个位数
g = lambda x: x % 10
print(g(10))
print(g(101))
print(g(1234))

# 获取一个字符串的最后一个字符  未知量 一个   功能 获取最后一个字符
h = lambda x: x[-1]
print(h('afbgjhkdsg'))
print(h('dsjgha'))

# 获取一个数的10倍
f = lambda x:x*10
# 获取两个数的平均数
f1 = lambda x,y:(x+y)/2

高阶函数

把函数A作为另外一个函数B的参数或者返回值的形式,称为高阶函数

# 获取列表中的最大值  封装成函数
def get_max0(l):
    max_value = l[0]
    for i in l[1:]:
        if i > max_value:
            max_value = i
    return max_value
print(get_max0([12, 332, 43, 23, 203]))

# 获取列表中 个位数最大的值
def get_max1(l):
    max_value = l[0]
    for i in l[1:]:
        if i % 10 > max_value% 10:
            max_value = i
    return max_value

print(get_max1([9, 14, 18, 27, 45]))

# 获取列表中单词长度最长的
def get_max2(l):
    max_value = l[0]
    for i in l[1:]:
        if len(i) > len(max_value):
            max_value = i
    return max_value

print(get_max2(['zow', 'are', 'you', 'very']))

# 把整体求最大 封装成一个函数
# key 指定 求xxx最大  长度 个位数  最后一个字符
def get_max(l,key=None):
    max_value = l[0]
    for i in l[1:]:
        # 如果key不指定 求数值最大   如果key 指定了 按照指定的规则求最大
        if key == None:
            # 要比较的两个内容  i  max_value
            compare_ele,compare_max = i,max_value
        else:
            compare_ele, compare_max = key(i),key(max_value)
        if compare_ele>compare_max:
            max_value = i
    return max_value

print(get_max(['zow', 'are', 'you', 'very'], key=len))
print(get_max([9,17,36,25], key=lambda x:x%10))
print(get_max([9, 17, 36, 25]))
print(get_max([-100, 50, 60],key=abs))
# 获取 各个位上的和最大    key 实现的功能  求一个数各个位上的和
def get_sum(num):
    res = 0
    a = str(num)
    for i in a:
        res += int(i)
    return res

print(get_sum(19))
print(get_sum(100))
print(get_max([19, 123, 234, 100, 200, 500], key=get_sum))












内置高阶函数
max(序列,key)  
max(arg1,arg2,*args,key)

min(序列,key)

排序 
sorted(序列,key,reverse)   产生一个新的序列 不影响原有数据   任意序列排序 
列表.sort(key,reverse)  只能排列表  影响的是原列表  

map 映射  将序列中的元素映射为指定内容
map(函数,序列)    返回的是 map对象   list(map(函数,序列)) 查看

filter 筛选  将序列中的元素按照指定的规则筛选 
filter(函数,序列)   返回的是 filter 对象  list(filter(函数,序列)) 查看

reduce 累计   先导入  from functools import reduce 
reduce(函数,序列)   累加  lambda x,y:x+y 
				    累乘  lambda x,y:x*y 

# max()
print(max([-100, 20, 30, 40], key=abs))  # -100
print(max(19, 28, 37, 66, key=lambda x: x % 10))  # 19
print(max(19, 28, 37, 66))  # 66
print(max('how', 'are', 'very', 'thanhs', key=len))  # thanhs
print(max('how', 'are', 'very', 'thanhs', key=lambda x: x[-1]))  # very
print(max('how', 'are', 'very', 'thanhs', key=lambda x: x[1]))  # are
# min()
# 排序的   列表的操作  sort(key,reverse)  默认升序排  reverse=True  降序   修改是列表本身
l = [19, 44, 58, 26]
l.sort(key=lambda x: x % 10)
print(l)
# 高阶函数  任何序列可用  sorted()   不修改源数据  产生一个新的
# sorted(iterable,key,reverse)    iterable  序列   key 排序方式    reverse 是否降序
print(sorted('thanks'))
print(''.join(sorted('thanks')))  # ahknst
print(sorted(['how', 'very', 'am', 'I', 'thanks'], key=len, reverse=True))
print(sorted(('how', 'very', 'am', 'I', 'thanks'), key=len, reverse=True))
d = {'数学': 99, '语文': 100, '英语': 77}
# 按照成绩排序 升序   #  二维  [(数学,99),(语文,100),(英语,77)]
print(sorted(d.items(), key=lambda x: x[-1]))
students = [
	{'学号': 1, '姓名': '乐乐', '年龄': 12, '性别': '男', '成绩': 71},
	{'学号': 2, '姓名': '倩倩', '年龄': 11, '性别': '女', '成绩': 83},
	{'学号': 3, '姓名': '苗苗', '年龄': 13, '性别': '女', '成绩': 98},
	{'学号': 4, '姓名': '旭旭', '年龄': 12, '性别': '男', '成绩': 65},
	{'学号': 5, '姓名': '花花', '年龄': 11, '性别': '男', '成绩': 66}]
print(sorted(students, key=lambda x: x.get('成绩')))
# map 映射    列表推导式  不需要筛选
# map(func,序列)
# 获取每个数的10倍
print(list(map(lambda x: x * 10, [1, 2, 3, 4, 5])))   # [10, 20, 30, 40, 50]
# 每一个元素 转化为字符串
print(list(map(str, [1, 2, 3, 4, 5])))    # ['1', '2', '3', '4', '5']

# filter   筛选   筛选序列满足条件的
# filter(func,序列)
print(list(filter(lambda x: x % 2 == 0, range(1, 11))))    # [2, 4, 6, 8, 10]
# 第一个参数可以为None   按照布尔转换规则 获取 为True对应的值
print(list(filter(None, range(0, 10))))   # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 累计
from functools import reduce
# reduce(func,序列)
print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]))   # 15
print(reduce(lambda x, y: x * y, range(1, 11)))    # 3628800
print(reduce(lambda x, y: str(x) + '_' + str(y), [1, 2, 3, 4, 5]))



函数嵌套

在一个函数中声明了另一个函数

def outer():
    print('这是外部函数')
    def inner():
        print('这是内部函数')
    # 第一种
    # inner()
    # 第二种方式
    return inner

f = outer()   # f = inner
print(f)
f()     # inner()




闭包

能够读取到其他函数内部数据的函数称为闭包

如果想在一个函数中读取到另一个函数的数据,只有一种形式,函数嵌套

闭包的特点

  • 函数嵌套
  • 内部函数中持有外部函数的数据
  • 外部函数的返回值为内部函数的引用 return inner

自由变量:外层函数的变量被内部函数所使用,这个变量就会变成自由变量

自由变量与普通局部变量的区别:

  • 普通的局部变量会随着函数的调用结束,在内存中释放
  • 自由变量,被内部函数所持有,不会被释放

函数中修改全局变量 global进行修饰

如果在函数嵌套的内层函数 修改外层函数的变量 需要nonlocal 进行修饰

def outer():
    name = '小明'  # 没有被内部函数所使用  普通的局部变量
    age = 18   # age   自由变量
    print('这是outer中的age:',age)
    def inner():
        nonlocal age  # 告诉解释器 变量 来源于 外部函数
        age = 19
        print('这是inner中的age:',age)
    return inner
f = outer()
# 查看当前引用的自由变量
print(f.__closure__)

def outer():
    name = '小明'  # 没有被内部函数所使用  普通的局部变量
    age = 18   # age   自由变量
    print('这是outer中的age:',age)
    def inner():
        nonlocal age  # 告诉解释器 变量 来源于 外部函数
        age = 19
        print('这是inner中的age:',age)
    inner()
    print(age)  # 外层函数中

outer()
装饰器

作用:本质是在简化代码,在不修改原有代码的基础上,增加新的功能

装饰器 其实就是闭包

def 外层函数名(变量名):
	def 内层函数名(*args,**kwargs):
		原有功能 
		新的功能
	return  内层函数名
	
@外层函数名
def my_add(x,y):
	return x+y
import time

def my_add(x,y):
    time.sleep(0.1)
    return x+y
def sleep():
    time.sleep(0.2)

# 求和
print(my_add(102, 30))

# 计算函数的执行时间   函数执行前  测量一个当前时间   执行函数   函数执行完成之后  测量一下当前时间
start_time = time.time()  # 返回的是一个时间戳     1900-1-1 到  当前时间的秒数
print(my_add(10, 20))
end_time = time.time()
# print(end_time-start_time)


start_time = time.time()
sleep()
end_time  = time.time()
# print(end_time-start_time)
#
# # 把测量时间封装成函数    需要测量时间的函数 未知   参数
def get_time(func,*args,**kwargs):
    start_time = time.time()
    # 函数的调用
    res = func(*args,**kwargs)
    end_time = time.time()
    print( f'{func.__name__}的执行时间是{end_time-start_time}')
    return res
# # 测量时间
# print(get_time(sleep))
# print(get_time(my_add,x=10,y=20))
# print('------------------------')
# # 想要调用 my_add  不仅能求和  还能测量时间
# other = my_add    #  other 接受my_add 的功能   求和  other 的功能  求和
# my_add = get_time   # 把 get_time  地址 给了 my_add  指向的 get_time  get_time的功能
# print(my_add(other,x=10,y=20))   # 实际上调用  get_time
#
# # sleep的执行时间  sleep()
# other = sleep  # other  持有的是 sleep 休眠的额功能
# sleep  = get_time  # sleep 持有的是 get_time 的功能
# sleep(other)  # 实际上调用  get_time
#
# # 重复操作 封装成函数    传递过来一个函数       返回给一个函数 get_time
# def trans(other):
#     return get_time
# print('=================')
# 想在一个函数中 持有另一个函数的变量  函数嵌套
def trans(other):
    def get_time(*args, **kwargs):
        start_time = time.time()
        # 函数的调用
        res = other(*args, **kwargs)
        end_time = time.time()
        print(f'{other.__name__}的执行时间是{end_time - start_time}')
        return res
    return get_time

# my_add = trans(other = my_add)  # trans(other = my_add) 为 get_tiem
# print(my_add(x=10,y=20))  # 调用的是 get_time
#
# sleep = trans(other=sleep)   # 可以用语法糖@
# sleep()

@trans   # my_add = trans(other = my_add)
def my_add(x,y):
    time.sleep(0.1)
    return x+y

@trans   # sleep = trans(other=sleep)
def sleep():
    time.sleep(0.2)


print(my_add(10, 20))
sleep()
import time


def trans(other):
    def get_time(*args, **kwargs):
        start_time = time.time()
        # 函数的调用
        res = other(*args, **kwargs)
        end_time = time.time()
        print(f'{other.__name__}的执行时间是{end_time - start_time}')
        return res

    return get_time


@trans  # my_add = trans(other = my_add)
def my_add(x, y):
    time.sleep(0.1)
    return x + y

@trans  # sleep = trans(other=sleep)
def sleep():
    time.sleep(0.2)

print(my_add(10, 20))
# sleep()
# print(my_add(50, 20))

# 模块的导入
# 应用的测试文件为 demo_model.py

# 第一种 import 模块名   使用  模块名.方法名
import string模块05
# print(string.ascii_letters)

# 第二种  from 模块名  import 方法名    使用  方法名
# from string import ascii_letters,ascii_uppercase,ascii_lowercase
#
# print(ascii_letters)
# print(ascii_uppercase)
# print(ascii_lowercase)

# 自定义模块导入
# import demo_model
# #
# print(demo_model.my_add(10, 20))   #  30
# print(demo_model.my_mul(10, 20))

from demo_model import my_add,my_mul

# print(my_add(10, 20))
# print(my_mul(10, 20))


# from demo_model import *
#
# print(my_add(10, 20))
# print(my_mul(10, 20))

包和模块

模块:就是一个python文件

模块分为三种:

​ 内置模块【系统模块】,三方模块【别人写好上传的,我们能够下载使用】,自定义模块【自己写的】

模块之间可以相互调用,引入模块的方法

import  模块名   
	使用方法  模块名.方法名  
	
from 模块名  import  方法名     from  functool import reduce    
	使用方法  方法名  
	
from 模块名 import *     不建议使用引用方法  
	* 泛指 该模块下的所有内容  
	但是如果在模块中使用了 __all__ 限定了对外公开的内容   只能获取到对外公开的内容  

包:其实是特殊的文件夹

和普通文件夹【目录】的区别:包自带一个__init__.py的文件,调用包中的内容时候,首先执行__init__.py中的内容

包的作用:1. 能py文件进行分类管理 2. 增大命名空间

引入包中内容

import 包名.包名1.包名2.模块
	使用方法  包名.包名1.包名2.模块.方法名 
起别名  
import 包名.包名1.包名2.模块 as 新名字 
	使用方法  新名字.方法名 
	
from 包名.包名1.模块名  import  方法名
	使用方法   方法名
	
from 包名.包名1.模块名 import *  
	* 泛指该模块下的所有内容  如果有__all__  只能获取__all__中的内容 

一个python文件有两种使用方法, 第一种:直接运行文件, 第二种:作为模块被其他文件导入

当是第一种情况,直接执行文件,这个文件有一个属性 __name__ = __main__

当是第二种情况,被其他文件导入 ,这个文件的属性 __name__ = 模块名字

如果在一个文件中,有些内容当直接执行这个文件的时候,运行内容,如果被作为模块导入的时候,不运行

string模块
import string

# 获取所有的大写   结果为字符串
print(string.ascii_uppercase)
# 获取所有的小写
print(string.ascii_lowercase)
# 获取所有的英文
print(string.ascii_letters)
# 获取所有的数字
print(string.digits)     # 0123456789
# 获取所有的八进制
print(string.octdigits)   # 01234567
# 获取所有的十六进制数据
print(string.hexdigits)   # 0123456789abcdefABCDEF
# 获取所有的空白字符
print(string.whitespace)
# 获取所有的可打印的内容
print(string.printable)
# 获取所有的标点符号
print(string.punctuation)   # !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~







random模块
import random
import string
# 产生指定范围中的随机整数  包含结束位置
print(random.randint(1, 100))
# 在容器中随机选择一个元素
print(random.choice('dhjfg'))
print(random.choice(['男','女']))
# 在容器中随机选择多个  通过参数指定选择的个数  选择的内容可能是重复   有放回获取
print(random.choices(string.ascii_lowercase, k=4))
# 在容器随机选择多个  选出的内容不重复  无放回获取
print(random.sample('abcde', k=4))
# 产生 [0,1) 范围中的随机小数
print(random.random())
print(round(random.random(), 2))
# [0,10)中的随机小数
print(random.random()*10)
# 随机打乱列表的顺序
num = [1,2,3,4,5]
random.shuffle(num)
print(num)






math模块
import math

# 取绝对值  abs 内置函数  abs(-10)  -- 10       fabs是math模块中   返回值为浮点型数据
print(math.fabs(-10))   #  10.0
print(abs(-10))
print(abs(-5.5))
# 求某个数的n次幂   math.pow 返回结果为浮点型数据
print(math.pow(2, 5))   # 32.0
print(pow(2, 5))    # 32
# 求和    math.fsum    无精度损失求和
print(math.fsum([0.1] * 10))   # 1.0
print(sum([0.1] * 10))    # 0.9999999999999999
# 向上取整   10.1 -- 11  10.9 -- 11  取给定的值大的 最小的整数
print(math.ceil(10.1))   # 11
print(math.ceil(-5.5))    #  -5
# 向下取整   比给定值小的  最大的整数
print(math.floor(10.1))  # 10
print(math.floor(-5.5))  # -6
# 求阶乘    循环   封装个函数    递归    reduce
print(math.factorial(10))    # 3628800
# 对数函数    log
print(math.log2(32))   # 5.0
# 三角函数
# 圆周率
print(math.pi)   # 3.141592653589793
# 求sin
print(math.sin(math.pi / 2))   # 1.0
print(round(math.cos(math.pi / 2)))
# 弧度转角度
print(math.degrees(math.pi))   # 180.0
# 角度转弧度
print(math.radians(360))      # 6.283185307179586






calendar模块
import calendar

# 获取某年的日历
print(calendar.calendar(2023))
# 获取某年某月的日历
print(calendar.month(2023, 8))
# 判断某年是否为闰年
print(calendar.isleap(2023))
# 获取两个年分之间闰年的个数 不包含结束
print(calendar.leapdays(2000, 2020))   # 6
# 获取某年某月某日 是星期几  从 0开始    0 表示星期一  1 表示星期二
print(calendar.weekday(2023, 8, 2))   # 2





time模块
import time

# 休眠  休眠的时间单位 秒
time.sleep(0.1)
# 获取时间戳  指的是 1900-1-1 到当前时间【运行文件的】 经历的秒数
print(time.time())    # 1690959297.5859387
# 获取当前时间的时间元组
time_tuple = time.localtime()
# tm_year 年  tm_mon  月   tm_mday 日   tm_hour 小时   tm_min 分钟   tm_sec 秒   tm_wday 星期几 从0开始    tm_yday  这一年的第xx天
# time.struct_time(tm_year=2023, tm_mon=8, tm_mday=2, tm_hour=14, tm_min=56, tm_sec=13, tm_wday=2, tm_yday=214, tm_isdst=0)
print(time_tuple.tm_wday)   # 2
print(time_tuple.tm_yday)   # 214
# 获取某年某月某日是这一年的第多少天   如果获取 这个年月日对应的时间元组
# 时间格式化   把时间元组 按照指定的格式 显示出来    返回结果是 字符串
# time.strftime('时间的格式',时间元组)
# 时间的格式  %Y 年  %m 月  %d 天  %H 24小时制  %I 12小时制   %M 分钟  %S 秒  %p AM PM  %w 表示星期几   %j 这一年的第多少天
s = time.strftime('%Y-%m-%d %H:%M:%S', time_tuple)
print(s,type(s))   # 2023-08-02 15:07:14
print(time.strftime('%Y/%m/%d %H:%M:%S', time_tuple))   # 2023/08/02 15:07:39
print(time.strftime('%d/%m/%Y %H:%M:%S', time_tuple))   # 02/08/2023 15:07:59
print(time.strftime('%Y/%m/%d %p %I:%M:%S', time_tuple))   # 2023/08/02 PM 03:08:58
# 时间反格式化  把字符串形式的时间 变成时间元组   解析字符串形式的时间  解析模板
# time.strptime(字符串形式的时间,解析模板)  注意: 解析模板和字符串形式时间一一对应
print(time.strptime('2023-07-31 13:24:56', '%Y-%m-%d %H:%M:%S'))
print(time.strptime('2023-07-31 13:24:56', '%Y-%m-%d %H:%M:%S'))
# 获取时间元组对应的时间戳
print(time.mktime(time_tuple))   #1690960469.0
# 获取时间戳对应的时间元组
print(time.localtime(1690950469.0))

# 获取某年某月某日是这一年的第xxx天
# 如果是时间元组 tm_yday 获取第xxx天
# 指定时间的时间元组   时间反格式化
t = time.strptime('2023-07-15 00:00:00','%Y-%m-%d %H:%M:%S')
print(t)   # time.struct_time(tm_year=2023, tm_mon=7, tm_mday=15, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=196, tm_isdst=-1)
print(t.tm_yday)   # 196

def get_day(year,month,day):
    return time.strptime(f'{year}-{month}-{day} 00:00:00','%Y-%m-%d %H:%M:%S').tm_yday


print(get_day(2023, 3, 2))  # 31+28+2 =  61
print(get_day(2023, 2, 28))  # 59







datetime模块
import datetime
import time

'''
datetime模块中 
date类
time类
datetime类
timedelta类
'''
# 构造时间 date
d = datetime.date(2023, 8, 2)
print(d, type(d))  # 2023-08-02 <class 'datetime.date'>
# 构造时分秒 time
s = datetime.time(17, 20, 30)
print(s, type(s))  # 17:20:30 <class 'datetime.time'>
# 构造 年月日 时分秒  datetime
t = datetime.datetime(2023, 8, 2)
print(t, type(t))  # 2023-08-02 00:00:00 <class 'datetime.datetime'>
t = datetime.datetime(2023, 8, 2, 15, 56)
print(t, type(t))  # 2023-08-02 15:56:00 <class 'datetime.datetime'>
# 获取当前时间
cur_datetime = datetime.datetime.now()  # 2023-08-02 15:57:18.839978
print(cur_datetime, type(cur_datetime))  # 2023-08-02 15:58:02.110725  <class 'datetime.datetime'>
# 单独获取某些内容
# 获取年
print(cur_datetime.year)  # 2023
print(cur_datetime.month)
print(cur_datetime.day)
print(cur_datetime.hour)
print(cur_datetime.minute)
print(cur_datetime.second)
# 获取年月日
print(cur_datetime.date())  # 2023-08-02
# 获取星期
print(cur_datetime.weekday())  # 2   从0开始

# 时间格式化   把datetime 变成 字符串格式
# 时间对象.strftime(格式化模板)
str_time = cur_datetime.strftime('%Y/%m/%d %p %I:%M:%S')
print(str_time, type(str_time))  # 2023/08/02 PM 04:04:56 <class 'str'>

# 时间反格式化  把字符串时间变成时间对象
# datetime.datetime.strptime(字符串时间,解析模板)
t = datetime.datetime.strptime('2023/08/02 16:06:30', '%Y/%m/%d %H:%M:%S')
print(t, type(t))  # 2023-08-02 16:06:30  <class 'datetime.datetime'>
# 获取时间戳  获取时间对象的时间戳
# 时间对象.timestamp()
print(cur_datetime.timestamp())  # 1690963764.917123
# 将时间戳转化为时间对象
print(datetime.datetime.fromtimestamp(1690963764))  # 2023-08-02 16:09:24


# 获取某年某月某日是这一年第多少天  第二个思路
# 时间元组  tm_yday  获取天
# 时间元组   通过时间戳也可以获取时间元组   time.localtime(时间戳)
# 时间戳   指定时间 求时间戳       时间对象.timestamp()
# 时间对象    反格式化          datetime.datetime.strptime(字符串时间,解析模板)
def get_day(year, month, day):
    # 先构造时间对象
    time_obj = datetime.datetime.strptime(f'{year}-{month}-{day} 00:00:00', '%Y-%m-%d %H:%M:%S')
    # 获取时间对象所对应的时间戳
    t = time_obj.timestamp()
    # 把时间戳变成时间元组
    t_tuple = time.localtime(t)
    return t_tuple.tm_yday


print(get_day(2023, 2, 28))
print(get_day(2023, 3, 28))

# 时间差
# 求两个时间的差值  时间
d1 = datetime.datetime(2023, 8, 2, 16, 23, 30)
d2 = datetime.datetime(2023, 7, 15, 12, 20, 18)
print(d1, d2)
# 求差值
time_diff = d1 - d2
print(time_diff)  # 18 days, 4:03:12
# 只想要 差值中的天数
print(time_diff.days)  # 18
# 获取除天数之外的秒数
print(time_diff.seconds)  # 14592
# 获取包含天数在内的所有秒数
print(time_diff.total_seconds())  # 1569792.0
# 获取几天后的时间       时间 + 差值
# 获取 3天后的时间
t = datetime.datetime.now()
print(t + datetime.timedelta(days=3))  # 2023-08-05 16:27:47.147097
# 获取两周后的时间
print(t + datetime.timedelta(weeks=2))  # 2023-08-16 16:28:45.652284
# 获取某年某月某日 是这一年的第多少天   比较额是 年-1-1  构造两个时间  求差 获取天数       2023-1-31   2023-1-1
def get_day2(year, month, day):
    # 构造两个时间  给定的时间  这一年的1月1日
    d1 = datetime.datetime(year, month, day)
    d2 = datetime.datetime(year, 1, 1)
    return (d1 - d2).days + 1
print(get_day2(2023, 2, 2))

os模块
# 操作文件系统相关的模块
import os

# 查看当前目录的绝对路径
print(os.getcwd())   # C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13

# 创建文件夹 只能创建一级文件夹  mkdir 如果路径不存在 创建  但是如果路径存在 报错
# 判断路径是否存在 如果不存在  创建
if not(os.path.exists('./os模块')):
    os.mkdir('./os模块')

# 连续创建多级文件夹
# if not(os.path.exists('./demo/demo1/demo2')):
#     os.makedirs('./demo/demo1/demo2')

# 删除文件夹  删除一级文件夹  rmdir 空目录   如果目录中有文件 报错
# if os.path.exists('./os模块'):
#     os.rmdir('./os模块')
#
# # 连续删除多级空目录
# if os.path.exists('./demo/demo1/demo2'):
#     os.removedirs('./demo/demo1/demo2')

# 获取某个路径下直接包含的所有子文件和子文件夹
print(os.listdir('.'))  # 获取day13下直接包含的子文件和子文件夹

# 文件的重命名  路径不变 名字改变
# os.rename('./os模块','./os模块haha')
# 实现剪切的操作   路径改变 名字不变
os.rename('./os模块haha','./pack/os模块haha')



os.path
# 和路径相关
import os
# 判断路径是否存在
print(os.path.exists('./os模块'))
# 判断路径是否为文件
print(os.path.isfile('作业01.py'))
print(os.path.isfile('./os模块'))
# 判断路径是否为文件夹
print(os.path.isdir('作业01.py'))
print(os.path.isdir('./os模块'))
# 判断路径是否为绝对路径
print(os.path.isabs('./os模块'))  # False
print(os.path.isabs(os.getcwd()))  # True
# 根据相对路径获取对应的绝对路径
print(os.path.abspath('./os模块'))  # C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13\os模块
# 获取某个文件的大小
print(os.path.getsize('作业01.py'))  # 2662
# 获取某个路径的最后一级路径名
path = r'C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13\os模块'
print(os.path.basename(path))   # os模块
# 获取包含最后一级的路径
print(os.path.dirname(path))   # C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13
# 获取文件的后缀名
path2 = os.path.abspath('作业01.py')
# 如果给定的路径为文件夹  空字符串
print(os.path.splitext(path))   # ('C:\\Users\\86166\\Documents\\上课资料\\2303班python基础\\Day13\\代码\\BasicProject\\Day13\\os模块', '')
# 如果给定的路径是文件    后缀名
print(os.path.splitext(path2))  # ('C:\\Users\\86166\\Documents\\上课资料\\2303班python基础\\Day13\\代码\\BasicProject\\Day13\\作业01', '.py')
# 拼接路径
print(os.path.join(r'C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13', '作业01.py'))
# C:\Users\86166\Documents\上课资料\2303班python基础\Day13\代码\BasicProject\Day13\作业01.py


面向对象

面向对象是一种编程思维

类和对象

类:把同一类对象的共同特征提取出来,形成一个抽象的概念

对象:在这个类下实实在在存在的实体就是对象 字符串类 ‘abc’

飞机模型图   --  类 
根据图造出来的机器  -- 对象  

如何构造一个类 :

先对对象进行分析,找到共同的特征和共同的行为,对这些信息进行描述,形成一个类

特征称为对象的属性,行为称为对象的方法 【函数】

定义类的语法 

class 类名(父类类名):
	# __init__  给该类的对象添加属性的  
	def __init__(self,参数1,参数2):
		self.特征名 = 参数1
		self.特征名 = 参数2  
	
	# 行为  方法  一个个的函数 
	def 函数名():
		pass  

解读 
class -- 定义类的关键字  
类名 -- 建议使用大驼峰命名法   
	大驼峰命名法  每一个单词的首字母都大写   AnimalZoo
	小驼峰命名法  第一个单词的首字母小写,其他单词首字母大写    animalZoo
	
(父类类名) -- 可以没有   继承   bool 继承自 int   class bool(int):
	默认继承自 Object  

__init__ 函数  给该类的对象添加属性的   函数名不能改   注意  __int__
	参数 self --  指的是调用该方法的对象   
		谁来调这个方法   self指的就是谁   
	self  名字可以改      
	
创建对象语法  
类名(参数【具体的特征值】)  参数传递到 def __init__(self,参数1,参数2)
# 创建 Dog
# 特征  名字  年龄  颜色
# 行为  嗷嗷叫  拆家
class Dog:
    # 为对象添加属性
    def __init__(self,name,age,color):
        # 给特征赋值
        self.name = name
        self.age = age
        self.color = color
    # 行为
    def aoao(self):
        print(self)
        print(f'{self.name}在嗷嗷叫')
    def chai_jia(self):
        print(f'{self.name}在拆家')
# 创建对象  一个类可以有多个对象     'a'  'ab'  'abc'
# Dog(特征的值)
dog1 = Dog('小白',5,'白色')
print(dog1)   # <__main__.Dog object at 0x000002A9EB8A8850>
dog2 = Dog('小黑',6,'黑色')
print(dog2)   # <__main__.Dog object at 0x000002A9EB6E1BB0>
dog3 = Dog('花花',3,'花色')
print(dog3)  # <__main__.Dog object at 0x000002A9F3FAE640>
print('----------------')
# 调用方法   对象.方法            字符串.upper()    列表.append()
dog1.aoao()
# dog1.chai_jia()
# # 调用属性   dog1的年龄  姓名  颜色
# print(dog1.name)   # 小白
print('----------------')
dog2.aoao()

# 定义学生类
# 特征  姓名  年龄  成绩
# 行为  干饭  睡觉  打游戏
class Student:
    def __init__(self,name,age,score):
        self.name = name
        self.age = age
        self.score = score
    # 函数 也可以有参数
    def gan_fan(self,where):
        print(f'{self.name}{where}干饭')
    def sleep(self):
        print(f'{self.name}正在睡觉')
    def play_game(self):
        print(f'{self.name}正在打游戏')

stu1 = Student('小明',20,80)
stu2 = Student('小红',18,78)

stu1.play_game()
stu2.gan_fan('芙蓉餐厅')

#  账户类
# 特征  账户号   账户所属人   账户余额
# 行为  存钱 【钱数】  取钱 【钱数 判断是余额够用  】   注意  账户余额   得变化

class Account:
    def __init__(self,cid,name,balance):
        self.cid = cid
        self.name = name
        self.balance = balance
    def save_money(self,num):
        self.balance += num
        print(f'{self.name}{self.cid}账户,成功存钱{num}元,余额为{self.balance}元')
    def get_money(self,num):
        if num > self.balance:
            print(f'当前余额为{self.balance},余额不足')
        else:
            self.balance -= num
            print(f'{self.name}{self.cid}已经取了{num}元,现有余额为{self.balance}元')

a1 = Account(101,'小明',10000)
a1.save_money(1000)
a1.get_money(2000)



















类和类之间的关系
use-a关系 依赖关系

定义一个类的时候需要借助另一个类的信息来完成

# 小明在北京市昌平区北科院学习
# 面向对象
# 类  人   属性  名字  行为  学习
# 地点   属性  市   区   地点

class Place:
    def __init__(self,city,area,place):
        self.city = city
        self.area = area
        self.place = place

class Person:
    def __init__(self,name):
        self.name = name

    def study(self,where):
        print(f'{self.name}{where.city}{where.area}{where.place}学习')

# 构建对象
p1 = Place('北京','昌平','北科院')
stu = Person('小明')
#
stu.study(p1)





has-a关系

定义一个类的属性,这个属性是另外一个类的对象

# 把一个类的对象    作为另一个类的属性
'''
学生类
    特征 学生编号  姓名  年龄  性别  成绩
    行为 干饭 学习

班级类
    特征  班级名称  学生们 -- 学生 (对象)
    行为   添加学生   删除学生   排序   筛选
'''
class Student:
    #
    def __init__(self,sid,name,age,gender,score):
        self.sid = sid
        self.name = name
        self.age = age
        self.gender = gender
        self.score = score
    # def __repr__
    def __repr__(self):
        # 返回的内容  自定义  你想要返回什么形式  写成什么形式
        # return f'{self.name}--{self.age}--{self.gender}--{self.score}'
        return f'Student(编号:{self.sid},姓名:{self.name},年龄:{self.age},性别:{self.gender},成绩:{self.score})'

class ClassRoom:
    # 创建教室中  有学生 多个学生  容器  添加 删除 -- 可变   students 学生们 哪个教室的教室? self
    def __init__(self,cname,students=None):
        if students == None:
            students = []
        # 对每个特征进行初始化赋值
        self.cname = cname
        self.students =students      
    # 查看每一个对象的学生们
    def show_all_student(self):
        return self.students
    # 添加学生  所有学生  容器 列表  添加学生  向列表中添加数据   【1,2,3】   [].append(4)
    def add_stu(self,student):
        self.students.append(student)
    # 删除学生  指定删除学生的特点  根据学生的编号删除
    def remove_stu(self,sid):
        for stu in self.students:   # stu  学生对象  拥有学生的属性  sid  name score age gender
            if stu.sid == sid:
                # 列表中删除某个数据 pop()  索引   根据元素删   remove
                self.students.remove(stu)
                break
        else:  # else 循环完成
            print('没有这个学生')

s1 = Student(1,'小明',5,'男',88)
s2 = Student(2,'小红',6,'女',82)
s3 = Student(3,'小蓝',5,'男',98)
s4 = Student(4,'小花',4,'女',68)
s5 = Student(5,'小强',7,'男',78)

class1 = ClassRoom('python')
class2 = ClassRoom('h5',[s1,s2])

print(class1.show_all_student())
print(class2.show_all_student())

# 添加学生
class2.add_stu(s3)
print(class2.students)

# 删除学生
class2.remove_stu(1)
print(class2.students)
class2.remove_stu(4)







is-a关系 继承关系

子类拥有父类的属性或者方法

class Student:
    def __init__(self, sid, name, age, gender, score):
        self.sid = sid
        self.name = name
        self.age = age
        self.gender = gender
        self.score = score

    def __repr__(self):
        return f'({self.name} -- {self.score})'


class ClassRoom:
    def __init__(self, classname, students=None):
        if students == None:
            students = []
        self.classroom = classname
        self.students = students

    # 添加学生  所有的学生中  列表   列表.append()
    def add_stu(self, stu):
        self.students.append(stu)

    # 删除学生  根据xxx删除  编号
    def remove_stu(self, num):
        for stu in self.students:
            if stu.sid == num:
                self.students.remove(stu)
                break
        else:
            print('没有该学生')

    # 排序  列表 对列表排序  sorted
    def sort_by_score(self):
        return sorted(self.students, key=lambda x: x.score, reverse=True)

    # 获取 指定性别的人数   男  女
    def get_num_from_gender(self, gender):
        c = 0
        for stu in self.students:
            if stu.gender == gender:
                c += 1
        return c

    # 获取每个性别对应的人数  字典结构
    def classify_by_gender(self):
        d = {'男': 0, '女': 0}
        for stu in self.students:
            if stu.gender == '男':
                d['男'] += 1
            else:
                d['女'] += 1
        return d
s1 = Student(1, '小明', 5, '男', 88)
s2 = Student(2, '小红', 6, '女', 82)
s3 = Student(3, '小蓝', 5, '男', 98)
s4 = Student(4, '小花', 4, '女', 68)
s5 = Student(5, '小强', 7, '男', 78)
class1 = ClassRoom('h5', [s1, s2])
class1.add_stu(s3)
print(class1.students)
class1.remove_stu(1)
print(class1.students)
print(class1.sort_by_score())
print(class1.get_num_from_gender('女'))
print(class1.classify_by_gender())

类属性和对象属性

类属性是直接定义在类中,被所有的对象所共有

类属性 可以类进行调用 可以对象进行调用 但是只能类进行修改

对象属性定义在 __init__中,每个对象独有的特征,构建对象的时候自动为每一个对象进行添加

对象属性来说,随着对象一起创建,所以当对象被销毁,对应的属性也被销毁

对象属性只能对象调用

class Dog:
    # age 类属性
    age = 10
    def __init__(self,name,color):
        # name  color 对象属性
        self.name = name
        self.color = color
# 定义对象
dog1 = Dog('小白','白色')
dog2 = Dog('小花','花色')
# 对象属性只能对象来调用
print(dog1.name)
print(dog1.color)
# 类属性被所有对象所共有  可以类调用 可以对象调用
print(dog1.age)
print(dog2.age)
print(Dog.age)
# 但是 只能类进行修改   获取再赋值
Dog.age = 18
print(dog1.age)
print(dog2.age)
# 如果对象调用并赋值
print('-------------------------------')
dog1.age = 100   # 如果对象调用并赋值  做的不是修改的操作 而是给对象添加了一个age的特征
print(dog1.age)
print(dog2.age)
print(Dog.age)
















魔术方法

不需要手动调用,在适当的时机进行自行调用,魔术方法前后各有两个下划线

__new__   构造方法   实例化一个对象的时候自行调用  
__init__  初始化方法  为对象添加属性  执行时机在 __new__ 之后  
__str__   当print(对象)的时候,打印出来是一个地址,如果想自定义内容,需要重写__str__
__repr__  想透过容器看到对象的自定义内容,需要重写 __repr__
__del__   析构方法  当一块内存地址没有任何引用的时候,自动触发  


运算符 
__add__  
__sub__
__mul__
__truediv__
__gt__   greater  than
__ge__   greater  equal
__lt__   less
__le__

__eq__    ==  
	如果在类中没有重写 __eq__ 那判断的是内存地址是否一样  和is是一样的 
	但是通常情况下 == 是用来判断伪相等 

class Dog:
    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return f'***{self.name}***'
    def __repr__(self):
        return f'Dog({self.name}-{self.age})'
dog1 = Dog('小白',5)
dog2 = Dog('小黑',6)
print(dog1)
print([dog1,dog2])




#如果 创建一个类 传列表  当使用乘法  对每一个数据 *这个数
# [1,2,3]*10 = [10,20,30]
class A:
    def __init__(self,ls):
        self.ls = ls
    def __mul__(self, other):
        return [i*other for i in self.ls]
a = A([1,2,3,4])
print(a*10)

# __eq__  ==
# 身份证  号  姓名
class Card:
    def __init__(self,name,cid):
        self.name = name
        self.cid = cid
    def __eq__(self, other):
        return self.name == other.name
c1 = Card('小明1','1234')
c2 = Card('小明1','12345')
print(c1 == c2)



继承

本质上是简化代码,将两个或者两个以上相关联的类提取共同的特征和共同的方法,提取到一个共同类中,然后通过指定的语法使用共同类中的信息,这种格式称为继承

相关联的类称为子类,共同类称为父类、超类、基类

子类和父类的关系:子类继承自父类,父类派生出子类

体现继承的语法

class 类名(父类):
	

方法重写:

1. 子类的实现和父类部分一样
  1. 子类的实现和父类完全不一样

当子类对父类中的方法进行重写之后,从子类的角度来说,是子类的方法覆盖了父类的方法,子类调用只能调用重写后的

'''
学生类
    特征  姓名  年龄  性别
    行为  干饭  学习

工人类
    特征  姓名  年龄  性别  工龄
    行为  干饭  挣窝囊费

人类
    特征  姓名  年龄  性别
    行为  干饭
'''
class Person:
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender= gender
    def gan_fan(self):
        print(f'{self.name}干饭')

class Student(Person):
    def study(self):
        print(f'{self.name}学习')

class Worker(Person):
    def __init__(self,name,age,gender,work_age):
        # 使用父类的其中三个参数
        # 使用方法一  父类类名.__init__(self,参数1,参数2,参数3)
        # Person.__init__(self,name,age,gender)
        # 使用方法二    super(子类类名,self).__init__(参数1,参数2,参数3)
        # super(Worker,self).__init__(name,age,gender)
        # 使用方式三   super().__init__(参数1,参数2,参数3)
        super().__init__(name,age,gender)
        # 初始化第四个
        self.work_age = work_age
    def get_salary(self):
        print('今日窝囊费到手!')
    def gan_fan(self,food):
        print(f'{self.name}正在干{food}')

# 创建工人对象
w1 = Worker('小明',30,'男',6)
w1.gan_fan('烤盘饭')





# 创建学生对象
# stu1 = Student('小明',5,'男')
# stu1.gan_fan()
# stu1.study()
多继承

子类继承自多个父类,所有父类的方法都可以继承,但是如果多个父类中的方法一样,默认继承自第一个父类

class A1:
    def __init__(self,leg):
        self.leg = leg
    def run(self):
        print('跑跑跑')

class A2:
    def __init__(self,wing):
        self.wing = wing
    def fly(self):
        print('飞飞飞')

class Son(A1,A2):
    def __init__(self,leg,wing):
        A1.__init__(self,leg)
        A2.__init__(self,wing)

s1 = Son(4,5)
s1.run()
s1.fly()

垃圾回收机制

python中使用引用计数原则实现垃圾回收机制

核心思想:每一个python对象都有一个计数器,初始 实例化对象 计数器值为0,

当对象每增加一个引用,计数器+1,反之,取消了对该对象的引用,计数器就会-1,当计数器回到0,表示没有任何引用,证明程序不再需要,调用__del__ 进行垃圾回收

import sys
class Dog:
    def __init__(self,name):
        self.name = name
    def __del__(self):
        print(f'{self.name}正在调用__del__')

dog1 = Dog('小明')
print(sys.getrefcount(dog1))   # 2  文档中解释  得到的结果会预期 +1
# 增加引用
a =  dog1
print(sys.getrefcount(dog1))   # 3
b = dog1
print(sys.getrefcount(dog1))   # 4
c = dog1
print(sys.getrefcount(dog1))   # 5
# 删除引用
c = 10
print(sys.getrefcount(dog1))  # 4
b = 20
print(sys.getrefcount(dog1))   # 3
a = 5
print(sys.getrefcount(dog1))  # 2
del dog1
# print(sys.getrefcount(dog1))  #  name 'dog1' is not defined
print('---------------------------------')


可迭代对象、迭代器与生成器

可迭代对象:能够进行迭代逐一返回成员的对象称为可迭代对象,能够实现for - in遍历

str list tuple dict set range

实现了一个可迭代协议,实现了__iter__()函数

迭代器:不仅能使用for-in遍历,还能使用next() 进行迭代操作

不仅实现了可迭代协议__iter__(),还实现了__next__()

迭代器一定是可迭代对象 但是 可迭代对象不一定是迭代器

但是 可迭代对象 可以变成 迭代器 ,通过使用 iter(可迭代对象)

迭代器是可以记录位置的对象,从第一个元素开始访问,直到所有的元素访问结束,只能往前不能后退

1 2 3 4  
1 
2 3 4  

生成器:有两种实现方式

  1. 生成器表达式 – 列表推导式 [] ---- ()
  2. 在函数中 使用 yield 代替 return
    1. 调用函数的时候,不会进入函数中,而是返回一个生成器
    2. 获取生成器中元素的时候,才会进入函数中,遇到yield,暂停在这个位置,并把结果抛出,当获取下一个元素,从上次暂停的位置开始执行

生成器的本质就是迭代器,用于批量产生数据

和列表推导式的区别:

列表推导式批量产生的数据直接存在在内存中

生成器,需要一个,在内存中产生一个 ,同一时间只存储一个值 节省内存空间

可迭代对象 > 迭代器 > 生成器

# 类
from collections.abc import Iterable,Iterator,Generator
# Iterable   可迭代对象  Iterator   迭代器     Generator   生成器
# 可迭代对象  for-in     __iter__
l = [1,2,3]
t = (1,2,3)
s = '123'
print(isinstance(l, Iterable))   # True
print(isinstance(t, Iterable))   # True
print(isinstance(s, Iterable))   # True

# 迭代器   不仅for-in   next()    __iter__   __next__
  # 组合   结果  二维数据
z = zip(['A','B'],[1,2])
print(z)
print(isinstance(z, Iterator))   # True
# 特点
# next()
# print(next(z))   # ('A', 1)
# print(next(z))   # ('B', 2)
# print(next(z))   # StopIteration
print('------')
for i in z:
    print(i)
print('------')
for i in z:
    print(i)
# map    filter  --- 迭代器
# 普通的可迭代对象 可以变成迭代器  iter()
l = [1,2,3,4]
for i in l:
    print(i)
for i in l:
    print(i)
# 把l 变成迭代器
l1 = iter(l)
print(isinstance(l1, Iterator))
print(l1)  # <list_iterator object at 0x000001526A6E9670>
print(next(l1))
print('-------------------')
for i in l1:
    print(i)
# 生成器
# 有两种产生 形式  生成器表达式   [] --- ()
g = (i for i in range(10))
print(g)    # <generator object <genexpr> at 0x000002BFEE51DDD0>
print(isinstance(g,Generator))   # True
print(next(g))  # 0
print('----------')
for i in g:
    print(i)
print('----------')
for i in g:
    print(i)

# 函数  return -- yield
def get_num():
    for i in range(10):
        yield i
        print('---------------')
l = get_num()
print(l)   # <generator object get_num at 0x000001ED82F14E40>
print(next(l))
print(next(l))
print(next(l))


异常捕获

异常:程序遇到不正常情况,导致程序的中断

常见的异常 :

# ZeroDivisionError
# NameError
# IndentationError
# KeyError
# TypeError   

异常捕获就是将可能出现错误的代码使用 try 包含,使用 except 列出可能出现的异常进行捕获,保证代码的正常运行,不被中断

try:
	可能出现错误的代码 
except 异常类型 as 变量名:
	如果try的出错原有满足异常类型,做的解决方案 
except 异常类型1 as 变量名:
	如果try的出错原有满足异常类型1,做的解决方案
except 异常类型2 as 变量名:
	如果try的出错原有满足异常类型2,做的解决方案
# 如果对所有的错误 解决方案一样  
except Exception as 变量名:
	解决方案
else:
	当且仅当try中的内容没有错误 执行的代码 
finally:
	不管try中代码有没有错误,都要执行  
	场景: open()  --  关闭      数据库连接  


# a =5
# # print(1/0)
# # if a==5:
# # d ={'数学':99}
# # print(d[0])
# print(a[0])
# print('hahah')
# print('hahahha')
# print('hahahahahha')

# ZeroDivisionError
# NameError
# IndentationError
# KeyError
# TypeError

# 异常捕获
# for i in range(-1,2):
#     a = 1/i
#     print(a)
for i in range(-1,2):
    try:
        a = 1/i
    except Exception as e:
        # 如果出错了  执行的内容
        print('哈哈哈 有错了',e)
    else:# 当 try中没有错误  打印
        print(a)
    finally:
        print('中午吃点啥')

# 抛出异常
month = int(input('请输入月份'))
if month not in range(1,13):
    raise ValueError('月份没有在指定范围中')












正则表达式

一种特殊的字符串,拥有自己独特的语法,可以进行判断或者验证操作

适用于所有的语言,python中提供的正则表达式模块是re模块

拥有独立的处理引擎,效率比使用字符串的方法要低,能用系统字符串用字符串,不能用或者处理较麻烦的使用正则

爬虫:解析数据的其中一种方式就是正则解析

正则相关用法

import re  

re.compile(正则表达式,匹配标记) --- 将正则表达式编译成正则对象 

正则对象.match(字符串对象) -- 从字符串的最左边开始匹配满足正则对象的内容
	如果最左边开始匹配失败 不再进行匹配  

正则对象.search(字符串对象) -- 在字符串中搜索满足正则对象的内容,
	如果有,返回的是第一个,如果没有,返回None

正则对象.fullmatch(字符串对象)  -- 从字符串的左边开始到右边结束验证是否满足正则对象 
	
正则对象.findall(字符串对象) -- 在字符串中查找所有满足正则对象的内容。
	结果放在列表中,如果没有找到,返回空列表
	
正则对象.split(字符串对象) -- 将正则对象匹配到的内容为切割符号,进行切割 

正则对象.sub(新的数据,字符串对象) -- replace
	将正则对象匹配到的内容替换为新内容 

正则语法
匹配单个字符
符号含义
.通配符,表示的是除 \n 之外的任意字符
[字符们]表示的是这个位置可以是字符们中的任意一个字符
a[abc] – ab aa ac
a[0-9] 如果ascii连续 可以用 - 连接
a[A-Za-z0-9]
a[^0-9] ^表示的取反的含义 除xxx之外都可以 非0-9之间的内容
\d表示的是0-9中任意一个符号 和[0-9]表示含义相同
\D表示的非 0-9 和[^0-9] 表示含义相同
\w数字、字母、下划线中的任意一个
\W表示 非数字、非字母、非下划线中任意一个
\s表示的空白字符
\S表示的非空白字符
限制开头和结尾
符号含义
^指定内容表示字符串以指定内容开头
指定内容$表示字符串以指定内容结尾
数量词
符号含义
*表示的是前面的符号出现任意次 可以是0 可以是1 可以是多 >=0
+表示的是前面的符号出现至少1次 可以是1 可以是多 >=1
?表示的是前面的符号出现至多1次 要么是0 要么是1 0或者1
{m}表示的是前面的符号出现m次
{m,n}表示的是前面的符号出现至少m次 至多n次 {3,5}
{m,}表示的是前面的符号出现至少m次 至多无限次
分组匹配

某个位置的元素有多种情况,使用()包含组合数据,多种情况之间使用|表示或者

贪婪模式和非贪婪模式

* + {m,} 表示的数量 向上无限,贪婪模式

取消贪婪模式 使用?进行组合 *? +? {m,}? 匹配到合理的位置自动停止

匹配标记
符号含义
re.I ( i )忽略大小写
re.S让 . 匹配所有 包含 \n
import re

# 创建正则对象
re_obj = re.compile('a.')  # .表示的是 除\n之外的任意一个字符
# 正则对象.match()
# re_obj.match(字符串)
print(re_obj.match('abcde'))  # <re.Match object; span=(0, 2), match='ab'>
print(re_obj.match('a1cde'))  # <re.Match object; span=(0, 2), match='a1'>
print(re_obj.match('a\tcde'))  # <re.Match object; span=(0, 2), match='a\t'>
print(re_obj.match('a\ncde'))  # None
print(re_obj.match('mabcde'))  # None
# 正则对象.search()  整个字符串中查找 如果有多个  只能找到匹配到的第一个
print(re_obj.search('abcde'))  # <re.Match object; span=(0, 2), match='ab'>
print(re_obj.search('mabcde'))  # <re.Match object; span=(1, 3), match='ab'>
print(re_obj.search('ma1abcdame'))  # <re.Match object; span=(1, 3), match='a1'>
print(re_obj.search('bcde'))  # None
# 正则对象.fullmatch()    全部匹配   要求 正则表达式 和 字符串内容 完全匹配   从最左边到最右边
print(re_obj.fullmatch('abcd'))  # None
print(re_obj.fullmatch('a0'))  # <re.Match object; span=(0, 2), match='a0'>
print(re_obj.fullmatch('a\r'))  # <re.Match object; span=(0, 2), match='a\r'>
print(re_obj.fullmatch('a\n'))  # None
# 正则对象.findall()  找满足正则表达式的所有的内容   返回结果是列表   列表中存储的是满足正则表达式的数据
print(re_obj.findall('abca0ca1ca\tca\ncamc'))  # ['ab', 'a0', 'a1', 'a\t', 'am']
print(re_obj.findall('bcde'))  # []

# 单个匹配字符
# 创建正则对象
re_obj = re.compile('a[abc]')
print(re_obj.findall('amaoabarac'))  # ['ab', 'ac']

re_obj = re.compile('a[0-9]')
print(re_obj.findall('amaoabaraca0a5'))  # ['a0', 'a5']

re_obj = re.compile('a[0-9A-Za-z]')
print(re_obj.findall('amaoaMaraca0a5'))  # ['am', 'ao', 'aM', 'ar', 'ac', 'a0', 'a5']

re_obj = re.compile('a[^0-9]')
print(re_obj.findall('amaoabaraca0a5'))  # ['am', 'ao', 'ab', 'ar', 'ac']

re_obj = re.compile('a\d')
print(re_obj.findall('amaoabaraca0a5'))  # ['a0', 'a5']

re_obj = re.compile('a\D')
print(re_obj.findall('amaoabaraca0a5'))  # ['am', 'ao', 'ab', 'ar', 'ac']

re_obj = re.compile('a\w')
print(re_obj.findall('ama_a你a我aca+a5'))  # ['am', 'a_', 'a你', 'a我', 'ac', 'a5']

re_obj = re.compile('a\W')
print(re_obj.findall('ama_a你a我aca+a5'))  # ['a+']

re_obj = re.compile('a\s')
print(re_obj.findall('a a\ta\va\ra\fa\na5'))  # ['a ', 'a\t', 'a\x0b', 'a\r', 'a\x0c', 'a\n']

re_obj = re.compile('a\S')
print(re_obj.findall('a a\ta\va\ra\fa\na5'))  # ['a5']

# 限制开头和结尾
re_obj = re.compile('^a.$')  # fullmatch
print(re_obj.search('ab'))  # <re.Match object; span=(0, 2), match='ab'>

re_obj = re.compile('a.$')
print(re_obj.search('a2a1a0'))  # <re.Match object; span=(4, 6), match='a0'>

re_obj = re.compile('^a.')
print(re_obj.search('a2a1a0'))  # <re.Match object; span=(0, 2), match='a2'>
print(re_obj.search('1a2a1a0'))  # None

# 验证手机号是否合法   11位 数字   135
re_obj = re.compile('^135[0-9]{8}$')
re_obj = re.compile('^135\d{8}$')
print(re_obj.fullmatch('13500000031'))

# 验证手机号 是否以  135 或者 166 或者 188开头
re_obj = re.compile('1(35|66|88)\d{8}')
re_obj = re.compile('(135|166|188)\d{8}')
print(re_obj.fullmatch('18700000031'))

# 密码 6-12位  首个字母为大写英文字母  其他为英文字母或数字
re_obj = re.compile('^[A-Z][a-zA-Z0-9]{5,11}$')
print(re_obj.search('A12jdhhj4G6'))

# 字符串的切割 和 字符串的替换
s = 'how!are,you+thanks much'
# 切割成单词
print(s.split('!,'))
# 正则表达式
# 产生正则对象
re_obj = re.compile('[!,+ ]')
print(re_obj.split(s))  # ['how', 'are', 'you', 'thanks', 'much']

# 替换
s = 'a1b2c3d4e5你6我7'
# 要求  把所有的数字替换成空字符串
# print(s.replace('1', '').replace('2', '').replace('3', ''))
# 使用正则
# 创建正则对象  所有的数字
re_obj = re.compile('\d')
print(re_obj.sub('', s))  # abcde你我

s = '你123345好啊你ghkgdkfjgaf好啊你kfjg)_(&^%好啊'
# 获取s中所有你好中间的内容
# 创建正则对象
re_obj = re.compile('你(.*?)好')
print(re_obj.findall(s))

s = '<a href="http://news.baidu.com" target="_blank" class="mnav c-font-normal c-color-t">新闻</a>' \
    '<a href="https://www.hao123.com?src=from_pc" target="_blank" class="mnav c-font-normal c-color-t">hao123</a>' \
    '<a href="http://map.baidu.com" target="_blank" class="mnav c-font-normal c-color-t">地图</a>' \
    '<a href="http://tieba.baidu.com/" target="_blank" class="mnav c-font-normal c-color-t">贴吧</a>' \
    '<a href="https://haokan.baidu.com/?sfrom=baidu-top" target="_blank" class="mnav c-font-normal c-color-t">视频</a>' \
    '<a href="http://image.baidu.com/" target="_blank" class="mnav c-font-normal c-color-t">图片</a>'

# 获取   新闻  hao123   地图
re_obj = D('<a href="(.*?)" target="_blank" class="mnav c-font-normal c-color-t">(.*?)</a>')
print(re_obj.findall(s))  # ['新闻', 'hao123', '地图', '贴吧', '视频', '图片']
# [('http://news.baidu.com', '新闻'), ('https://www.hao123.com?src=from_pc', 'hao123'), ('http://map.baidu.com', '地图'), ('http://tieba.baidu.com/', '贴吧'), ('https://haokan.baidu.com/?sfrom=baidu-top', '视频'), ('http://image.baidu.com/', '图片')]


# 易错点  .     匹配  qq.com  163.com   126.com  sina.com
re_obj = re.compile('^(qq|163|126|sina)\.com$')
print(re_obj.search('sina.com'))

# 简化语法
# 正则对象 = re.compile(正则表达式,匹配标记)
# 正则对象.findall()
# ==================  简化语法
# re.findall(正则表达式,字符串对象,匹配标记)
print(re.search('^(qq|163|126|sina)\.com$', 'sina.com'))


# 匹配标记
# 查找所有的 a.  A.
print(re.findall('a.', 'a1A2amAk', re.I))   # ['a1', 'A2', 'am', 'Ak']

# 查找所有的 a.
print(re.findall('a.', 'a1a\ta\na '))   # ['a1', 'a\t', 'a ']
print(re.findall('a.', 'a1a\ta\na ',re.S))  #  ['a1', 'a\t', 'a\n', 'a ']

# 查找所有 a.  A.    包含 \n
print(re.findall('a.', 'a\nA\namAm', re.I | re.S))   # ['a\n', 'A\n', 'am', 'Am']

# 验证变量名是否合法
'''
要求:
1. 组成是由数字 英文字母 下划线   [0-9a-zA-Z_]    
2. 不能以数字开头
3. 长度 6-12位
'''
print(re.search('^[a-zA-Z_][0-9a-zA-Z_]{5,11}$', 'hhgfdg'))





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谨慎填写的用户名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值