---
title: python基础语法
date: 2025-03-09 15:01:02
categories:
  - 人工智能基础
---



------

# 前言

语言：Python（python==3.9）

编译软件：VScode、PyCharm

环境：Anaconda

# 一、Python注释和输入输出

注释分为单行注释，多行注释，被注释的代码不会运行，快捷键：选中代码+Ctrl+/

主要功能有：

1.对代码进行注释，方便进行理解

2.对代码进行禁用

## 1.单行注释

```python
# 单行注释
# 我是一个注释 不是运行的代码 写代码的时候：Ctrl+/
# print("hello")
print(123)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**123

## 2.多行注释

```python
"""
三引号
引号内代码都注释
随便写多少行
"""
print("hello")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**hello

## 3.输入和输出

```python
# 输出
print("打印文本")
print("打印数字：",123)
print("文本1","文本2","文本3",sep = "-")
print("文本1",end = "\n")
print("文本2",end = "123")
print("文本3",end = "\n")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

打印文本
 打印数字： 123
 文本1-文本2-文本3
 文本1
 文本2123文本3

```python
# 输入
print(123)
x = input("打印到控制台，让程序暂停，等待用户输入")
print(x)
print(456)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

123
 444（将在控制台显示“打印到控制台，让程序暂停，等待用户输入”，等到用户输入后再运行下面的程序，这里输入444，输出444）
 456

# 二、变量

什么是变量：用一个简短的名称来代替数据的使用

## 1.数值

```python
a = 100
print(a)
print(100)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 2.字符串

```python
b = "我是一个字符串"
# 声明了一个变量，名字叫b,后面程序运行时可以直接用b来表示
print(b)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.变量名称的要求

一般场景下必须使用变量来保存数据，如果不需要使用到的数据需要接收，则用下划线“_”表示变量名

```python
x = 123
y = "nihao"
_ = 200
print(x,y,_)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

变量名字必须是连续的字母，下划线，数字的组合。错误的命名方法：first name = "123"

```python
firstname = "123123" #不会报错，但是不方便阅读
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

数字不可以作为变量名的开头，变量名严格区分大小写Name和name是两个不同的变量

```python
1app_version = "1.1.0"
print(1app_version)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

官方提供的关键字不可以作为变量名

```python
True = 10
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

中文作为变量名？可以，只要是Unicode编码符合的字符都可以作为变量名，一般约定用英文或者拼音字母而不用汉字

```python
华清远见 = "华清远见成都分中心在西南交大地铁站旁"
print(华清远见)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

常把大写字母的变量名作为不改变的常量使用

```python
PI = 3.14159
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.变量名命名规则

三种写法：

1.小驼峰：huaQingYuanJian

2.大驼峰：AppVersion

3.匈牙利命名法（比较常用）：ai_first_class_1

# 三、变量的赋值与取值

## 1.数据直接量

```python
x = 100
x_2 = "hello"
#取出变量中的数据并打印
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 2.表达式

```python
x_3 = x
print(x_3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.多变量一起赋值

```python
a = b = c = 100
print(a,b,c)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.解构赋值

```python
w,m,n = 100,10,1
print(w,m,n)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 5.变量的取值

```python
x = 10
x = 1#此时x最后被更新为1
print(x)#必须要等打印出来过后才执行后续的代码

x1 = 10
x2 = 20
x3 = 30
c = 666,x1,x2,x3
print(c)
x1,a,b,c= 666,x1,x2,x3
print(x1,a,b,c)

# 交换两个数据的取值
x1 = 10
x2 = 20
x1,x2 = x2,x1#x1<--x2,x2<--x1同时发生,优先级：先取值后赋值  生成一个元祖(x2,x1)==>(20,10)==>(x1,x2)
print(x1,x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 四、字符串

## 1.字符串的写法

```python
x_1 = "我是一个字符串"
x_2 = ""#空字符串
x_3 = " "#空格也是字符串
print(type(x_2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

```python
x1 = "hello"
x2 = "hi"
x3 = """三引号也可以是字符串
可以随意换行
自带换行符
"""
print(x3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

三引号也可以是字符串
 可以随意换行
 自带换行符

## 2.转义字符

```python
x1 = "我爱我的祖国和我的家乡\"四川\""
print(x1)
x2 = '我爱我的祖国和我的家乡\'四川\''
print(x2)
x3 = "我爱我的祖国和我的家乡'四川'"
print(x3)
x4 = "你好：\n  欢迎你"
print(x4)
x5 = "abcd\\efg\\hi"
print(x5)
x6 = "abc\tdef\tghi"
print(x6)
x7 = r"D:\桌面\华清\3.8\code\06-字符串.ipynb"#在字符串之前加r，表示\不转义
print(x7)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

我爱我的祖国和我的家乡"四川"
 我爱我的祖国和我的家乡'四川'
 我爱我的祖国和我的家乡'四川'
 你好：
  欢迎你
 abcd\efg\hi
 abc   def   ghi
 D:\桌面\华清\3.8\code\06-字符串.ipynb

## 3.字符串常用运算操作

**加号：**

```python
x1 = "华清远见"
x2 = "成都分中心"
str_1 = x1 + x2
print(str)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

```python
x3 = "我的年龄是："
x4 = "18"
str_2 = x3 + x4#只能字符串和字符串进行连接,两个变量的类型不匹配则不能拼接
print(str_2)

x5 = '华清''远见''666'#多个字符串靠在一起自动变成一个字符串
print(x5)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**乘号：**

```python
# 乘号
x6 = "abc"
str_3 = x6*3
print(str_3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

运行结果：

华清远见成都分中心
 我的年龄是：18
 华清远见666
 abcabcabc

**等号：（严格区分大小写）**

```python
x1 = "abc"
x2 = "Abc"
print(x1==x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

False

## 4.访问子串

```python
x7 = "华清远见成都分中心"
xx_7 = x7[0]
print(xx_7)

xx_77 = x7[-1]
print(xx_77)

xx__77 = x7[2:10:2]#切片,左闭右开，第三个数字代表每两个选中
print(xx__77)

xx__78 = x7[::2]
print(xx__78)

xx__79 = x7[:6:2]
print(xx__79)

xx__70 = x7[-1:6:2]
print(xx__70)

xx__74 = x7[9:3:-1]
print(xx__74)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

华
 心
 远成分心
 华远成分心
 华远成

心中分都成

**比较常用的三个：**

```python
xx__71 = x7[::-1]
print(xx__71)

xx__72 = x7[:-1]
print(xx__72)

xx__73 = x7[-1]
print(xx__73)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

心中分都成见远清华
 华清远见成都分中
 心

## 5.输入一个字符串，判断是否回文

```python
x1 = input("请输入字符串")# 这里输入：上海自来水来自海上
x2 = x1[::-1]
print(x1==x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**True

## 6.判断一个字符串是否为另一个字符串的子串

```python
x1 = "abcdefg"
x2 = "ab"
x3 = "gh"
print(x1 in x2)
print(x3 in x1)
print(x3 not in x1)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

False
 False
 True

## 7.查看字符串字符数量(长度)

```python
x1 = "abc"
n = len(x1)
print(n)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**3

## 8.常见占位符

```python
占位符和类型码

| 占位符和类型码 | 说明                                                         |
| :------------: | ------------------------------------------------------------ |
|       %s       | 转成字符串, 使用 str(x) 函数转换(常用)                       |
|       %d       | 转成十进制的整数(常用)                                       |
|       %o       | 转成八进制的整数                                             |
|     %x,%X      | 转成十六进制的整数                                           |
|     %e,%E      | 转成指数格式的浮点数                                         |
|     %f,%F      | 转成小数格式的浮点数(常用)                                   |
|     %g,%G      | 转成指数格式或小数格式的浮点数                               |
|       %%       | 转成一个%                                                    |
|     %m.nf      | m是指总宽度，默认右对齐，加个 - 表示左对齐，n 是指保留的小数点位数 |
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 9.字符串格式化表达式

常用来在训练自己的神经网络模型时，控制台查看数据情况

```python
x1 = "我叫%s今年%d岁"%("jack",23)
print(x1)

# 保留小数位数
x2 = "精确度是%.2f"%(100)
print(x2)

# 总宽度
x3 = "精确度是%50.3f"%(100)
print(x3)

# 进制转换
x4 = "十六进制的值是%x"%(11)
print(x4)

# 科学计数法
x5 = "科学计数法表示为%g"%(1000000000)
print(x5)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

我叫jack今年23岁
 精确度是100.00
 精确度是                      100.000
 十六进制的值是b
 科学计数法表示为1e+09

## 10.另外一种格式化字符串的方式

```python
r = 144
g = 127
b = 255
x1 = "rgb(144,127,255)"
x2 = f"rgb({r},{g},{b})"
print(x1)
print(x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

rgb(144,127,255)
 rgb(144,127,255)

## 11.字符串常用的一些API(别人写的一些函数，可以直接调用)

```python
# 将字母全部转换为小写
text = "HELLO world"
text2 = text.lower()
print(text2)

# 将字母全部转换为大写
text3 = text.upper()
print(text3)

# 首字母大写
text4 = text.capitalize()
print(text4)

# 去除两边空白字符
text = "  1825648  "
text5 = text.strip()
print(text5)

# 将字符串分割成列表(默认是空格)
text = "hello my name is jack"
text6 = text.split()
print(text6)
# 综合使用
text = "http://www.hqyj.com/index.html?user_id=123&user_name=jack&count=20"
text7 = text.split("?")[0]
print(text7)
text8 = text.split("?")[1].split("&")[1].split("=")[1]
print(text8)

# 连接字符串
text = ['hello', 'my', 'name', 'is', 'jack']
text9 = "-".join(text)
print(text9)

# 字符串替换
text = "你好，我叫李华"
text0 = text.replace("李华","李雷")
print(text0)

# 查找特定字符
text = "hello,my name is lihua"
text11 = text.find("lihua",19)#第二个参数代表起始下标，返回-1表示未查找到 
print(text11)

# 检查字符串是否以指定字符串开头
text = "std = 1"
text12 = text.startswith("std")
print(text12)

# 检查字符串是否以指定字符串结尾，返回布尔类型
text = "std = 1，name"
text13 = text.endswith("name")
print(text13)

# 是否全是数字
text = "1600"
text14 = text.isdigit()
print(text14)

# 是否只包含字母
text = "1600yuan"
text15 = text.isalpha()
print(text15)

# 是否只包含字母和数字字符
text = " price = 1600_yuan"
text16 = text.isalnum()
print(text16)

# 将字符串内每个单词首字母转变为大写
text17 = text.title()
print(text17)

# 将字符串首字母转变为大写
text18 = text.capitalize()
print(text18)

# 统计词频
text = "Hello, World! Hello, Python!"
text19 = text.count("Hello")
print(text19)

# 格式化字符串
name = "jack"
age = 18
text20 = f"my name is {name}, i am {age} year old"
print(text20)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

hello world
 HELLO WORLD
 Hello world
 1825648
 ['hello', 'my', 'name', 'is', 'jack']
 http://www.hqyj.com/index.html
 jack
 hello-my-name-is-jack
 你好，我叫李雷
 -1
 True
 False
 True
 False
 False
 Price = 1600_Yuan
 price = 1600_yuan
 2
 my name is jack, i am 18 year old
 False

# 五、数值型

## 1.进制

**十进制**

```python
x = 10
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**八进制，打印默认转化为十进制数**

```python
y = 0o100
print(y)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**十六进制**

```python
z = 0xD1BfD
print(z)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**二进制**

```python
m = 0b1010001
print(m)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

64
 859133
 81

## 2.浮点数与科学计数法

```python
x = 1.0
y = 2.
z = .6

# 科学计数法
x = 1e6
y = 2e03#0没有任何作用
z = 3e-3
import math
PI = math.pi
PI
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.数字类型转换

```python
x = 6
x1 = bin(x)
x2 = oct(x)
x3 = hex(x)
x4 = float(x)
x5 = complex(x)
x = 3.0
x6 = int(x)
print(x1,x2,x3,x4,x5,x6)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

math.ceil(x)函数返回大于或等于x的最小整数。
 math.floor(x)函数返回小于或等于x的最大整数。

```python
print(math.ceil(3.14))
print(math.floor(3.94))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

0b110 0o6 0x6 6.0 (6+0j) 3
 4
 3

## 4.布尔类型

```python
x = 0
print(bool(x))
y = ""
print(bool(y))
z = "0"
print(bool(z))
# 空的集合，列表，字符串都是True
print(10<20)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

False
 False
 True
 True

## 5.字节串和空值

```python
# 字节串
text = b"hello"
print(type(text))

# 空值
x = None#表示没有
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 六、列表

## 1.字面量

```python
x = []
print(type(x))
x = [1, 2, 3, 4, 5]
print(x)
x = [1, 2, [3,4]]
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 2.通过构造函数来创建列表

```python
x = list()
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.list函数可以传入一个可迭代对象用于创建列表中数据

```python
x = list("hello")
print(x)
# 或者
x = list(range(10))
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.列表的运算

```python
y = [4,5,6]
num = 5
z = x + y
print(z)
# 不能列表乘以列表，不能列表乘以浮点数
print(z)
z = x * num
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 5.in / not in

```python
x = ["a","b","c"]
print("a" in x)
print("b" not in x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 6.列表切片

```python
lst = [1,5,6,9,8,10]

# lst[起始下标:终止下标:步长]

# 取出一个元素

Lst_1 = lst[2]

# 取出多个元素

lst_2 = lst[2:5:2]

# 列表翻转

lst_3 = lst[::-1]

print(Lst_1,lst_2,lst_3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

6 [6, 8] [10, 8, 9, 6, 5, 1]

## 7.列表的操作

```python
x = [10, 20, 30]
re = x.append(40)# 直接修改列表，在列表末尾添加一行新数据
print(x,re)

x.insert(2,666)# 在索引为2的地方插入666
print(x)

# 可以传入一个可迭代对象
x.extend([9,99,999])
print(x)

# id函数可以查看一个变量保存的数据的地址
x_1 = [1,2,3]
print(id(x_1))
x_2 = [1,2,3]
x_3 = x_1 + x_2
x_1.extend(x_2)
print(id(x_1))
print(id(x_2))#不改变id地址
print(id(x_3))

# 修改，删除数据
x = [1,2,3,5,6,8,9,7,1,2]
x[2] = 666
print(x)
# 切片可以越界
print(x[2:100])
# 传入元素
x.remove(666)
print(x)
# 传入下标
x.pop(1)
print(x)
x.clear()
print(x)

# 删除变量，变量名不在支持被引用
x = [1,2,3,5,6,8,9,7,1,2]
del x
# print(x)报错

x = [1,2,3,5,6,8,9,7,1,2]
# 寻找第一个出现元素的下标
print(x.index(1))
print(x.index(max(x)))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

[10, 20, 30, 40] None
 [10, 20, 666, 30, 40]
 [10, 20, 666, 30, 40, 9, 99, 999]
 2303722066048
 2303722066048
 2303722068160
 2303722005568
 [1, 2, 666, 5, 6, 8, 9, 7, 1, 2]
 [666, 5, 6, 8, 9, 7, 1, 2]
 [1, 2, 5, 6, 8, 9, 7, 1, 2]
 [1, 5, 6, 8, 9, 7, 1, 2]
 []

0
 6

# 七、元组

元组和列表一样是保存数据的容器

## 1.创建元组

```python
x = ()
x = (1,2,3,5,6,8,5,4,2,5)
print(x)
print(x[1])
print(x[2:5])#得到一个新元组

# 只有一个数据,在后面打逗号
x = (10)
y = (10,)
print(type(x))
print(type(y))

x = 10,"hello",True
print(type(x))

x = tuple(range(5))
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

(1, 2, 3, 5, 6, 8, 5, 4, 2, 5)
 2
 (3, 5, 6)
 <class 'int'>
 <class 'tuple'>
 <class 'tuple'>
 (0, 1, 2, 3, 4)

## 2.元组的操作

```python
x = (1,"name","jack",6,5)
# 删除变量
# del x
print((x[1]))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.解构赋值

解构赋值必须左右的结构一致

```python
x1,x2 = (10,20)
print(x1,x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.元组的运算

```python
x = (10,20)
y = (30,40)
print(x+y)
print(x * 3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 5.将其他数据类型转换为元组

```python
x_1 = [1,2,5,6]
x_2 = "nihao","yes","no"
print(tuple(x_1),tuple(x_2))

count = x_2.count("no")
print(count)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 八、字典

## 1.创建空字典

字典的元素没有下标，只有键和值

```python
d = {}
print(d)
d = dict([("name","xiaowang"),("age",18)])
print(d)
d = dict(a = 1, b = 2, c = 3)
print(d)
# 字典的键不可以重复，否则后一个会覆盖前一个
title = {"name":"jack","age":"18","age":"10"}
print(title["age"])
# 并且需要是不可变类型，以此来访问数据，字典的键不存在会报错
title = {"name":"jack","age":"18","home":"beijing"}
print(title)
d = {(1,2,3):"id_num","age":18}
print(d)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{}
 {'name': 'xiaowang', 'age': 18}
 {'a': 1, 'b': 2, 'c': 3}
 10
 {'name': 'jack', 'age': '18', 'home': 'beijing'}
 {(1, 2, 3): 'id_num', 'age': 18}

## 2.字典的操作

```python
# 添加和修改和访问
title = {"name":"jack","age":18,"home":"beijing"}
title["age"] = 20
print(title)
title["school"]="swust"
print(title)
print(title["home"])
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{'name': 'jack', 'age': 20, 'home': 'beijing'}
 {'name': 'jack', 'age': 20, 'home': 'beijing', 'school': 'swust'}
 beijing

## 3.in/not in

只能用来判断键

```python
title = {"name":"jack","age":18,"home":"beijing"}
print("name" in title)
print("jack" in title)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

True
 False

## 4.删除字典

```python
title = {"name":"jack","age":18,"home":"beijing"}
del title["name"]
print(title)
title.clear()
print(title)
del title
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{'age': 18, 'home': 'beijing'}
 {}

## 5.常见API

```python
title = {"name":"jack","age":18,"home":"beijing"}
print(len(title))
print(type(title))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**
 3
 <class 'dict'>

把字典的字面量变成字符串，网络传输的时候，常常会把这种格式的字符串进行传输（JSON）

```python
str1 = str(title)
print(str1,type(str1))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**
 {'name': 'jack', 'age': 18, 'home': 'beijing'} <class 'str'>

## 6.字典的一些方法

```python
title = {"name":"jack","age":18,"home":"beijing"}
# 清空字典
title.clear()
print(title)

# 浅复制,存储地址不一样
# 因此更改其中一个不会对另外一个产生任何影响
title = {"name":"jack","age":18,"home":"beijing"}
str1 = title.copy()
print(str1)
print(id(title),id(str1))
str1["name"] = "mary"
print(str1,title)

# 获取字典中的数据
str2 = title.get("age")
print(str2)
str2 = title["age"]
print(str2)

# 若访问的键不存在，直接返回default的值
str2 = title.get("nn","None")
print(str2)

# 以可迭代对象来返回视图对象
items = title.items()
print(type(items))
for key,value in items:
    print(key,value)

# 返回键名
keys = title.keys()
for key in keys:
    print(key)

# 返回键值
values = title.values()
for value in values:
    print(value)

title_1 = {"name":"jack","age":18,"home":"beijing"}
title_2 = {"food":"vegetable"}
# 将title_2添加到title_1中
title_1.update(title_2)
print(title_1)

# 删除字典的某个键
title.pop("name")
# 也可以将age的值置空，但是键仍然占用空间
title["age"] = None
print(title)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{}
 {'name': 'jack', 'age': 18, 'home': 'beijing'}
 2594022048448 2594031191872
 {'name': 'mary', 'age': 18, 'home': 'beijing'} {'name': 'jack', 'age': 18, 'home': 'beijing'}
 18
 18
 None
 <class 'dict_items'>
 name jack
 age 18
 home beijing
 name
 age
 home
 jack
 18
 beijing
 {'name': 'jack', 'age': 18, 'home': 'beijing', 'food': 'vegetable'}
 {'age': None, 'home': 'beijing'}

# 九、集合

## 1.创建集合

```python
s1 = set()
print(s1)

# 传入数据是可迭代对象
# 自动排序
s2 = set([1,2,3,8,5])
print(s2)
s2 = set(range(5))
print(s2)

s3 = {10,20,30}
print(s3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

集合中不存在相同元素并且元素需要是不可变类型

```python
s4 = {10,20,(2,3),10,1}
print(s4)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**易混点**

```python
s5 = {(10)}

print(s5)

s6 = {(10,),(10,),}

print(s6)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{10}

{(10,)}

只有在python中相等，比较的是元素的值而不是地址

```python
x = (10,20)
y = (10,20)
print(x==y)
print(id(x)==id(y))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 2.案例

假设有一万个数字，每一个数字代表张图片的类别，用集合来查看到底有多少种类别

```python
x = [0,0,0,0,1,1,1,1,2,2,4,4,4,4,4,4,2,2,1,1,1,1,0,0,0,0,3,3,3,3,3,5,1,2,2,1]

print(set(x))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)



## 3.固定集合

不可以更改元素

```python
s1 = frozenset([1,2,3,4,5,5,6])

print(s1)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.eval()函数

常出现在企业级别的项目中,向项目中添加代码

```python
str1 = "10+20"

eval(str1)

lst = [1, 5, 6, 4, 5, 2, 3]

str2 = "+".join(map(str, lst))  # 将整数转换为字符串

print(eval(str2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 十、运算符

## 1.逻辑运算符

**A and B**

 A是一个表达式，B也是一个表达式

如果bool(A)为False，那么B不运行，否则整个表达式的结果为B的结果

```python
x1 = 100
x2 = 200
x3 = 0
x = x1 and x2
print(x)

x = x3 and x2
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

200
 0

**A or B**

如果bool(A)为True，那么B不运行，否则整个表达式的结果为B的结果

```python
x = x1 or x2
print(x)
x = x3 or x2
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

100
 200

**not A**

如果bool(A)为True，那么not A的结果为False，否则not A的结果为True

```python
x = not x1
print(x)
x = not x3
print(x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

False
 True

## 2.位运算符

```python
x1 = 0b1010

x2 = 0b1100

# 默认输出十进制数

print(x1 & x2)#按位与

print(x1 | x2)#按位或

print(x1 ^ x2)#按位异或

print(~x1)#按位取反
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

8

14

6

-11

```python
x1 = x1^x2

x2 = x1^x2

x1 = x1^x2

print(x1,x2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

运行结果：

12 10 

左移运算符

左移运算符是将一个数字的二进制位全部左移若干位，高位丢弃，低位补0。

```python
x1 = 0b1010

x2 = 2

print(x1 << x2)#左移运算符
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

右移运算符是将一个数字的二进制位全部右移若干位，低位丢弃，高位补0。

右移运算符

```python
x1 = 0b1010

x2 = 2

print(x1 >> x2)#右移运算符
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

40

2 

## 3.身份运算符

```python
a = 10
b = 10
print(a is b)  # True
print(a is not b)  # False
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 4.成员运算符

```python
a = [1, 2, 3, 4, 5]
b = 3
print(b in a)  # True
print(b not in a)  # False
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 5.三元运算符

```python
a = 10
b = 20
result = a if a > b else b
print(result)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

20

# 十一、表达式

\1. 算术表达式

 \2. 逻辑表达式

 \3. 关系表达式

\4. 赋值表达式

\5. 条件表达式

 \6. 位运算表达式

\7. 成员运算表达式

 \8. 身份运算表达式

# 十二、语句

标准的语句写法是每一个语句结束以后 用分号结尾

例如x = 10;，但是python不需要分号

语句分为单行语句和多行语句

## 1.if语句

```python
if 1 == 1:
    print("1 == 1")
else:
    print("1 != 1")

if 1 == 1:
    print("1 == 1")
elif 1 == 2:
    print("1 == 2")
else:
    print("1 != 1")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 2.循环语句

```python
# for循环
for i in range(2, 10,2):
    print(i)

# while循环
i = 1
while i <= 10:
    print(i)
    i += 1
else:
    print("循环结束")

# 死循环
# while True:
#     print("永远不会结束")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 3.break和continue语句

```python
# break语句
# break语句用于终止当前循环，并跳出循环体。
# python代码示例：

# 1. 无限循环
i = 0
while True:
    print(i)
    i += 1
    if i == 5:
        break

# 2. 条件循环
for i in range(10):
    if i == 5:   # 当i等于5时，跳出循环
        break
    print(i)
# continue语句
# continue语句用于跳过当前循环的剩余语句，直接开始下一轮循环。
# python代码示例：

for i in range(10):
    if i == 5:   # 当i等于5时，跳过当前循环的剩余语句，直接开始下一轮循环
        continue
    print(i)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 4.推导式

```python
# 列表推导式
x2 = [i**2 for i in range(1, 11) if i%2 == 0]
print(x2)
# 元组推导式
x3 = tuple(i**2 for i in range(1, 11))
print(x3)

# 字典推导式
key = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
x4 = {key[i]: i**2 for i in range(1, 11)}
print(x4)

# 集合推导式
x5 = {i**2 for i in range(1, 11)}
print(x5)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

[4, 16, 36, 64, 100]
 (1, 4, 9, 16, 25, 36, 49, 64, 81, 100)
 {'b': 1, 'c': 4, 'd': 9, 'e': 16, 'f': 25, 'g': 36, 'h': 49, 'i': 64, 'j': 81, 'k': 100}
 {64, 1, 4, 36, 100, 9, 16, 49, 81, 25}

# 5.with语句

```python
# with语句
with open("test.txt","r") as f:
  print(f)
  for line in f:
    print(line)
# with自动关闭文件


f = open("test.txt","r")
print(f)
for line in f:
  print(line)
f.close()# 手动关闭文件
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 十三、函数

## 1.声明函数

```python
def f1():
  print("f1运行")
f1()

def f2(x1,x2):
  print(x1+x2)
f2(5,6)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

return会让函数停止执行并返回结果

```python
def f2(x1,x2):
  return x1+x2
a = f2(6,6)
print(a)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

f1运行
 11
 12

## 2.参数的数量和位置

```python
# 参数数量和位置一致
def add(a, b):
    # return a + b
    return b + a

print(add(2, 3)) # 5

# 参数数量不一致
# def add(a, b):
#     return a + b + c
# print(add(2, 3)) # 语法错误，缺少参数c
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 3.关键字参数

先定义默认值，然后再调用时传入关键字参数

```python
def my_func(a, b, c=0, d=0):
    return a + b + c + d

print(my_func(1, 2, 3, 4)) # 10
print(my_func(1, 2, d=4)) # 6
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 4.元组解包参数

```python
def fn(a,b,c,*args):
  print(a,b,c)
  print(args,type(args))
fn(1,2,3)
fn(5,3,6,8,9,5,4,8)

def fn(*args):
  # 任意传几个参数
  print(*args)

fn(5,6,8)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：** 

1 2 3
 () <class 'tuple'>
 5 3 6
 (8, 9, 5, 4, 8) <class 'tuple'>
 5 6 8

## 5.字典解包参数

```python
def fn(a,b,**args):
  print(a,b)
  print(args,type(args))

fn(20,30)
fn(10,20,name="jack",age = "18")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

 **运行结果：** 

 20 30
 {} <class 'dict'>
 10 20
 {'name': 'jack', 'age': '18'} <class 'dict'>

***args 与 \**kwargs一起使用，可以接收任意数量的位置参数和关键字参数。**

```python
def my_func(*args, **kwargs):
    print(args)
    print(kwargs)

my_func(1, 2, 3, a=4, b=5)  
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

 **运行结果：** 

(1, 2, 3)
 {'a': 4, 'b': 5}

**只要是有下标的参数都可以解包**

```python
# 列表也可以解包
my_list = [1, 2, 3]
my_func(*my_list)  # 解包
# 也可以用字典解包
my_dict = {'a': 1, 'b': 2, 'c': 3}
my_func(**my_dict)  # 解包
# 元组也可以解包
my_tuple = (1, 2, 3)
my_func(*my_tuple)  # 解包
# 字符串也可以解包
my_str = '123'
my_func(*my_str)  # 解包
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 6.占位符

```python
def my_func(x, *, y):
  # *是一个占位符，他后面的参数必须是关键字参数
  print(x, y)
# my_func(1,2)报错，缺少关键字参数y
my_func(1, y=2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 7.匿名函数lambda

```python
fn=lambda x,y:x+y
print(fn(2,3))

fn = lambda x:"奇数" if x%2==1 else "偶数"
print(fn(11))
print(fn(2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**案例1：判断是否是闰年**

```python
def is_leap(year):
  if (year%4)==0 and (year%100)!=0:
    return True
  elif (year%400)==0:
    return True
  else:
    return False
print(is_leap(2024))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**案例2：按比例划分数据集**

```python
def train_test_split(data,train_size = 0.8):
    train_data = data[:int(len(data)*train_size)]
    test_data = data[int(len(data)*train_size):]
    return train_data,test_data
#测试
data = [1,2,3,4,5,6,7,8,9,10]
train_data,test_data = train_test_split(data,0.8)
print(train_data)
print(test_data)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：** 

[1, 2, 3, 4, 5, 6, 7, 8]
 [9, 10]

**函数分为三种：**

**官方内置函数，第三方函数，自己写的函数**

## **8.官方内置函数**

```python
# all传入的参数全部为True就返回True
x = [-10,0,30,-2]
re = all(x)
print(re)
# any只要有一个为True就返回True
print(any(x))
# sum(x)对x求和
print(sum(x))
# sorted(x)排序，key = fn表示按照函数返回值排序
def fn(x):
  return x**2
print(sorted(x,key = fn))
# reverse(x)反转，返回一个可迭代对象
print([i for i in reversed(x)])
# callable(x)检测x标识符是不是能够当函数调用
fn = 100
print(callable(fn))
fn = lambda x,y:x+y
print(callable(fn))
# zip(x,y)将x,y两个数据容器组合成一个可迭代对象,打包成元组
x = [10,20,30,40,50]
y = [40,50,60]
print([i for i in zip(x,y)])
# exec()将传入的字符串中的代码执行
exec("print('hello')")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

False
 True
 18
 [0, -2, -10, 30]
 [-2, 30, 0, -10]
 False
 True
 [(10, 40), (20, 50), (30, 60)]
 hello

## 9.globals和locals()

globals()返回值是一个字典，字典的key就是当前python环境全局变量的名字

```python
x = 10
y = 20
print(globals())
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

 **运行结果是一大串字典**

locals()返回值是一个字典，字典的key就是当前函数的局部变量的名字

```python
def fn(x,y):
  print(locals())
fn(1,2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

{'x': 1, 'y': 2}

## 10.filter函数

filter(函数，可迭代对象)，传入两个参数：函数和可迭代对象，返回一个经过函数筛选后的可迭代对象

```python
x = [1,2,2,3,5,6,4,8,5,2]
x2 = filter(lambda el:el%2==1,x)
print(list(x2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**实现：**

```python
def myfilter(fn,x):
  x2 = []
  for i in x:
    if fn(i) ==True:
      x2.append(i)
    else:
      continue
  return x2
def fn(x):
  if x%2==0:
    return True
  else:
    return False
re = myfilter(fn,[1,2,2,3,5,6,4,8,5,2])
print(re)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

[2, 2, 6, 4, 8, 2]

## 11.map函数

 map(函数，可迭代对象),与filter不同的是不需要进行筛选，直接经过函数映射到可迭代对象中

```python
x = [1,2,2,3,5,6,4,8,5,2]
def fn(x):
  return x**2
print(list(map(fn,x)))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**实现**

```python
def mymap(fn,x):
  x2 = []
  for i in x:
    x2.append(fn(i))
  return x2
def fn(x):
  return x**2
re = mymap(fn,[1,2,2,3,5,6,4,8,5,2])
print(re)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

[1, 4, 4, 9, 25, 36, 16, 64, 25, 4]

## 12.reduce函数

reduce(函数，可迭代对象，初始值）

reduce()函数会对可迭代对象中的元素进行累积操作，并将结果作为第一个参数传递给函数，然后再将结果和第二个参数传递给函数，以此类推，直到可迭代对象中的所有元素都被处理完。最后，reduce()函数返回累积结果。

```python
from functools import reduce
x = [1,2,4,3,5,6,4,8,5,2]
def fn(x1,x2):
  print(x1,x2,"=====")
  return x1+x2

reduce(fn,x)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**实现：**

```python
def myreduce(fn,x,start):
  x1 = fn(start,x[0])
  for i in range(len(x)-1):
    x1 = fn(x1,x[i+1])
  return x1
  # 简洁版 
  # def myreduce(fn,x,start):
  # re = start
  # for i in x:
  #   re = fn(re,i)
  # return re

def fn(x1,x2):
  print(x1,x2,"=====")
  return x1+x2
x = [1,2,4,3,5,6,4,8,5,2]
myreduce(fn,x,0)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

0 1 =====
 1 2 =====
 3 4 =====
 7 3 =====
 10 5 =====
 15 6 =====
 21 4 =====
 25 8 =====
 33 5 =====
 38 2 =====

## 13.作用域

作用域只针对函数，函数内部可以访问函数内部和外部的变量，但是函数外部不能访问函数内部的变量

```python
a = 100
def fn():
  q = 10
  a = 20#内层有a，访问内层作用域的a，外层没有，就去外层的外层，如果都没有就报错
  print(a)
  print(q)
  return a+q
print(fn())# 每次调用函数内部都会产生一个作用域，调用完毕后，内部创建数据使用的内存销毁
print(a)
# print(q)报错
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

20
 10
 30
 100

```python
b = [1,2,3,4,5,lambda x:x+1]
print(b[5](5))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

6

函数调用在A作用域 定义在B作用域，函数无论在哪个作用域中执行，一定是他定义的作用域下执行代码

```python
a = 100
def fm():
  print(a)

def fn():
  a = 200
  fm()

fn()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

100

**函数也是一种数据**

```python
def f1():

  a = 100

  def f2():

    print(a)

  return f2

a = 200

re = f1()

re()# 执行函数
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**作用域案例：**

```python
def fun(n = None,o = None):
  print(o)
  return {"fun":lambda m:fun(m,n)}

a = fun(0)
a["fun"](1)
a["fun"](2)
a["fun"](3)

b = fun(0)["fun"](1)["fun"](2)["fun"](3)

c = fun(0)["fun"](1)
c["fun"](2)
c["fun"](3)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

None
 0
 0
 0
 None
 0
 1
 2
 None
 0
 1
 1

## 14.修改变量值

```python
# def fn():
#   print(a)
#   a = 2
# fn()报错

a = 10
def fn():
  global a#声明全局变量
  print(a)
  a = 20#会访问全局变量a的值
fn()
print(a)


a = 10
def fn():
  global a
  a = 20
  def fm():
    global a
    print(a)#访问和修改全局作用域“a = 10”这个a
    a = 30
  fm()
fn()


a = 10
def fn():
  a = 20
  def fm():
    nonlocal a#访问和修改外层作用域“a = 20”这个a
    print(a)
    a = 30
  fm()
fn()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

10
 20
 20
 20

## 15.内建作用域

```python
print(__name__)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

__main__

## 16.递归

```python
def f(a):
  if a > 5:
    return a
  else:
    return f(a+1)

r = f(0)
print(r)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

6

函数返回值是一种数据，函数也是一种数据

```python
def fn():
  return 1+1
print(type(fn))
print(type(fn()))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

<class 'function'>
 <class 'int'>

## 16.回调函数 callback

把一个函数传入另外一个函数，传入的函数就是回调函数

定义一个工具函数，传入两个数和一个函数，调用传入的函数并返回结果

a,b可以是数据也可以是字符串，func必须是函数

```python
# 定义两个函数
def add(a,b):
  return a+b
def sub(a,b):
  return a-b
def calculate(a,b,func):
  return func(a,b)

# 传进去的add就是回调函数
print(calculate(5,3,add)) # 8
print(calculate(5,3,sub)) # 2
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

回调函数怎么体现：

遍历：把一个数据容器中的数据全部拿出来调用

设计一个工具函数：遍历列表中的所有元素，找出奇数拿来使用，但是这个工具自己并不适用

而是交给业务函数（回调）使用

```python
def find_odd(arr,cb):
  for el in arr:
    if el%2==1:
      cb(el)

x = [2,5,6,8,9,7]
def print_odd(el):
  print("找到一个奇数：",el)
find_odd(x,print_odd)
find_odd(x,lambda m:print(m**2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

找到一个奇数： 5
 找到一个奇数： 9
 找到一个奇数： 7
 25
 81
 49

## 17.闭包函数 block

函数内部有函数，内部的那个函数就是闭包函数

1.由于函数有作用域，而且多个函数的作用域是相互独立的

使用闭包函数把函数的值单独保存，让变量不要相互污染

2.由于函数调用和定义的作用域可以不是同一个，并且函数调用时是在定义的作用域中执行的

因此闭包函数可以在函数外部访问函数内部的变量

```python
def alipay():
  money_in = 100
  def tool():
    money_in = 300
    print(money_in)
  return tool
re = alipay()
re()
money_out = 200
print(money_out)
# print(money_in) 报错并没有更改程序内部的money，而是外部变量的money
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**案例**

```python
# 案例
def alipay():
  money1 = 200
  def tool(pwd,new_money):
    nonlocal money1
    if pwd == 123:
      money1 = new_money
    print(money1)

  def withdraw(pwd,amount):
    # 取钱
    nonlocal money1
    if pwd == 123:
      money1 -= amount
    print(money1)

  return tool,withdraw


def meituan():
  tool,withdraw = alipay()
  tool(123,666)
  # fn(321,777)

  withdraw(123,50)
meituan()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

666
 616

# 十四、装饰器

参考：[一文搞懂Python装饰器（通俗易懂） - 知乎](https://zhuanlan.zhihu.com/p/12722799041)

装饰器相当于一个闭包的调用，但是不同的是相较于Alipay的案例，不需要多余构建re变量，直接用@装饰器名字的方式来调用，相当于一种方便的写法

装饰器本质是回调函数和闭包函数的结合

装饰器本身是一个函数，把装饰的函数作为参数输入，然后吧调用封装在内部的闭包中，返回值那个闭包

**不带参数的装饰器**

```python
def fn():
  print("fn函数的业务是答应一句话：未来业务可能有很多行代码")


# 设计一个装饰器

def decorator(cb):
  def block1():
    print("装饰器执行的代码：怎么装饰由业务决定")
    cb()
    print("装饰器可以继续装饰：怎么装饰由业务决定")
  return block1

@decorator
def fn2():
  print("fn2函数的业务是打印一句话：未来就是具体业务代码")

fn2()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

装饰器执行的代码：怎么装饰由业务决定
 fn2函数的业务打印是一句话：未来就是具体业务代码
 装饰器可以继续装饰：怎么装饰由业务决定 

**带参数的装饰器：**

```python
# 带参数的装饰器
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before calling the function")
        func(*args, **kwargs)
        print("After calling the function")
    return wrapper

@my_decorator
def my_function(x, y):
    print("The sum of", x, "and", y, "is", x+y)
    return x + y

my_function(2, 3) # Output: 5  
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

Before calling the function
 The sum of 2 and 3 is 5
 After calling the function

作用：

1. ***\*[日志记录](https://zhida.zhihu.com/search?content_id=251567592&content_type=Article&match_order=1&q=日志记录&zhida_source=entity)\****：在函数执行前后自动添加日志记录，方便调试和监控程序行为。
2. ***\*[性能测试](https://zhida.zhihu.com/search?content_id=251567592&content_type=Article&match_order=1&q=性能测试&zhida_source=entity)\****：装饰器可以用来测量函数的执行时间，帮助识别性能瓶颈。
3. ***\*[权限验证](https://zhida.zhihu.com/search?content_id=251567592&content_type=Article&match_order=1&q=权限验证&zhida_source=entity)\****：在Web开发中，装饰器可以用于检查用户是否有权访问某个资源或执行特定操作。
4. ***\*[缓存](https://zhida.zhihu.com/search?content_id=251567592&content_type=Article&match_order=1&q=缓存&zhida_source=entity)\**（Memoization）**：通过装饰器实现函数结果的缓存，避免重复计算相同的输入值，从而提高效率。

# 十五、面向对象

## 1.类和对象的语法

定义一个类

```python
class Person:
  name = "张三"
  age = 18
  life = 1

  def fn(self,num):
    print("类中的函数叫做方法，参数是",num)

print(Person,type(Person))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

用这个类创造对象

```python
p1 = Person()
print(p1,type(p1))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

对象内部保存了很多数据，想要访问需要通过成员名

语法：对象名.成员名

```python
print(p1.name,p1.age,p1.life)

p1.fn(1)


p2 = Person()
p2.fn(2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

<class '__main__.Person'> <class 'type'>
 <__main__.Person object at 0x00000187F9C19940> <class '__main__.Person'>
 张三 18 1
 类中的函数叫做方法，参数是 1
 类中的函数叫做方法，参数是 2

## 2.__init__

实用类创建对象时，可以初始化对象的成员的值

**但是在Python当中__init__并不是构造函数，__new__才是**

__init__是一个魔术方法，是一个特殊的函数，会在创建对象时调用

```python
class Teacher:
  # 类名（10,20）的10和20会传给__init__函数的参数
  def __init__(self,name,age):
    print("__init__ name:",name,"年龄：",age)
    self.n = name# 给t1对象添加一个属性，属性名是n，属性中保存的值是：“xiaoming”，相当于赋值
    self.a = age
    

  def fn(self,name,age):
    print("fn name:",name,"年龄：",age)

t1 = Teacher("xiaoming",18)
t1.fn("xiaoming",18)
t1.a
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

__init__ name: xiaoming 年龄： 18
 fn name: xiaoming 年龄： 18

类每次创建对象时，创建对象有同样的属性和方法，而有一部分是创建的时候赋的值，有一部分创建的时候值一样

```python
class Game_person:
  life = 1
  def __init__(self,name,rank):
    self.name = name#前一个name是self的属性，后一个name是函数内部的一个变量
    self.rank = rank

# 可以创建很多个
g1 = Game_person("boss",2000)
g2 = Game_person("npc",100)
print(g1.name,g1.rank)
print(g2.name,g2.rank)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

boss 2000
 npc 100

## 3.对象语法

```python
class Box:
  x = 100
  def __init__(self,y):
    self.y = 200
  
  def change_y(self,new_y):
    print("调用函数前",self.y )
    self.y = new_y
    print("调用函数后",self.y )

b1 = Box(99)
b1.x = 200
print(b1.x)#只修改了b1的x值

b2 = Box(98)
print(b2.x)#b1的x值不变

b3 = Box(97)
print(b3.y)#这里y还是200

# 修改y的值,这里只修改b3的值，b1,b2不受影响，但是b1,b2也可以调用这个方法来修改值
# 第一种直接修改：
b3.y = 1
print("直接修改后",b3.y)
# 第二种常见一个修改y的函数来修改self.y：
b3.change_y(2)
print(b3.y)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

200
 100
 200
 直接修改后 1
 调用函数前 1
 调用函数后 2
 2

## 4.对象的方法内部可以操作这个对象的属性和方法

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

    def say_hello(self):
        print("Hello, my name is {} and I am {} years old.".format(self.name, self.age))

p1 = Person("Alice", 25)
p1.say_hello()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

Hello, my name is Alice and I am 25 years old.

## 5.对象的方法可以传入参数，也可以返回值。

```python
class Box:
  count = 100
  def __init__(self,m):
    self.m = m
  def cal_total(self,price):
    return self.count*self.m*price
  
b1 = Box(45)
re = b1.cal_total(108)
print(re)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

486000

**案例1**

假设有一个ATM类 用这个类创建出来的对象就是一个取款机对象

atm对象有一个属性 是一个列表 里面装了很多对象，每一个对象就是一个Person类型的对象

有一个属性 是一个数字 保存了余额

有一个方法可以往ATM里面添加Person对象

```python
class Person:
  def __init__(self,name,card_num,phone_num):
    self.name = name
    self.card_num = card_num
    self.phone_num = phone_num

class ATM:
  money = 5000
  persons = []
  def add_person(self,person):
    if person not in self.persons:
      self.persons.append(person)
      print("添加成功")
    else:
      print("该卡号已存在")

atm = ATM()
person1 = Person("张三","123456","13800138000")
person2 = Person("李四","654321","13800138001")
atm.add_person(person1)
atm.add_person(person2)
print(atm.persons[0].name)
print(atm.persons[0].card_num)
print(atm.persons[0].phone_num)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

添加成功
 添加成功
 张三
 123456
 13800138000

**案例2：**

公司员工管理系统

设计一个公司员工管理系统，包含以下内容：

\1. 定义一个 `Employee` 类，包含以下属性：

  \- `name`（姓名）

  \- `position`（职位）

  \- `salary`（薪水）

\2. 定义一个 `Company` 类，包含以下内容：

  \- 一个列表属性，用于存储 `Employee` 对象。

  \- 一个方法 `hire_employee`，用于招聘新员工。

  \- 一个方法 `fire_employee`，根据员工的姓名，解雇该员工。

  \- 一个方法 `list_employees`，用于列出公司中所有员工的信息。

  \- 一个方法 `total_salary`，计算公司所有员工的总薪水。

\3. 测试代码：

  \- 创建一个 `Company` 对象。

  \- 招聘几个员工。

  \- 列出所有员工。

  \- 解雇一个员工。

  \- 再次列出所有员工。

  \- 打印公司总薪水。

```python
class Employee:
  def __init__(self,name,position,salary):
    self.name = name
    self.position = position
    self.salary = salary

class Company:
  Employee_lst = []

  def hire_employee(self,Employee):
    if Employee not in self.Employee_lst:
      self.Employee_lst.append(Employee)
    else:
      print("已经添加该员工")

  def list_employees(self):
    for Employee in self.Employee_lst:
      print("name:",Employee.name,"position:",Employee.position,"salary:",Employee.salary)

  
  def total_salary(self):
    salary_total = []
    for Employee in self.Employee_lst:
      salary_total.append(int(Employee.salary))
    return sum(salary_total)

person1 = Employee("张三","经理","5000")
person2 = Employee("李四","客服","3000")
person3 = Employee("王五","地推","1000")

ali = Company()
ali.hire_employee(person1)
ali.hire_employee(person2)
ali.hire_employee(person3)

ali.list_employees()

salary = ali.total_salary()
print(salary)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

name: 张三 position: 经理 salary: 5000
 name: 李四 position: 客服 salary: 3000
 name: 王五 position: 地推 salary: 1000
 9000

## 6.类属性和类方法

```python
class qox:
  x = 100#他是一个类属性，这个类创建出来的实例也能访问
  def fn(self):
    print(qox.x)

# 两种调用方式
print(qox.x)
b1 = qox()
print(b1.x)

b1.x = 500
print(b1.x)#被更改
print(qox.x)#没有被更改，说明类自己本身也是一种数据容器
b1.fn()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：** 

100
 100
 500
 100
 100

## 7.类属性和类方法

它接收类本身作为第一个参数（通常命名为 cls），而不是实例（self）。

类方法可以访问类的属性和方法，但不能访问实例的属性

类变量是在类的定义中直接定义的变量，而不是在类的 __init__ 方法或其他实例方法中定义的。

类变量属于类本身，而不是属于类的某个实例

```python
class qox:
  x = 100#他是一个类属性，这个类创建出来的实例也能访问
  def fn(self):
    print(qox.x)

# 两种调用方式
print(qox.x)
b1 = qox()
print(b1.x)

b1.x = 500
print(b1.x)#被更改
print(qox.x)#没有被更改，说明类自己本身也是一种数据容器
b1.fn()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

显式的指定类方法

```python
class Box:
  x = 100
  def __init__(self,y):
    self.y = y
  def fn(self):
    print(self.x)
  
  @classmethod
  def fm(cls):
    print("fm被调用")
    print(cls.x)

b1 = Box(100)
# b1对象可以使用的成员：x,y属性,y方法 fn方法,fm方法
print(b1.x)
print(b1.y)
b1.fn()
b1.fm()

# Box可以直接访问fm
Box.fm()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**案例：类方法常可以作为工厂方法**

```python
class single:
  instance = None
  
  # 类方法：
  @classmethod
  def share_instance(cls):
    if cls.instance is None:
      cls.instance = single() 
      return cls.instance
    else:
      return cls.instance
    
s1 = single.share_instance()
s2 = single.share_instance()
# 两个是一样的
print(s1)
print(s2)

o1 = single()
o2 = single()
# 两个是不同的
print(id(o1))
print(id(o2))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

批量创建对象

```python
class student:
  def __init__(self, name, age):
    self.name = name
    self.age = age
  
  @classmethod
  def create_students(cls,num):
    arr = []
    for i in range(num):
      arr.append(cls(f"student{i}", i))
    return arr

# 直接创建两个学生对象
s1 = student("Alice", 20)
s2 = student("Bob", 21)
print(s1.name, s1.age)
print(s2.name, s2.age)

# 先初始化好学生数量，再去更改学生的属性
students = student.create_students(10)
students[0].name = "jack"
students[0].age = 22
print(students[0].name, students[0].age)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 8.静态方法

静态方法通常用于实现一些与类无关的工具函数，这些函数不需要访问类或实例的属性。

它们可以被类或实例调用，但不会影响类或实例的状态。

```python
class Box:
  count = 0
  def fn(self):
    print("fn普通方法")
  @classmethod
  def fm(cls):
    print("fm类方法")
  @staticmethod
  def fz():
    print("fn静态方法")
  @staticmethod
  def sigmod(x):
    return 1.0/(1.0+math.exp(-x))

Box.fm()
Box.fz()

b1 = Box()
b1.fz()

re = Box.sigmod(10)
print(re)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 9.构造方法

静态方法__new__ 方法负责创建并返回类的新实例，而 __init__ 方法则用于初始化实例。

```python
class Box:
  def __new__(self):
    print(self)
    return super().__new__(self)
  def __init__(self):
    self.width = 0

b1 = Box()
print(b1.width)
print(b1,Box)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 10.魔术方法

```python
class Person:
  # 初始化方法
  def __init__(self, name, age):
    self.name = name
    self.age = age

  # 打印方法
  # 打印对象时，会调用该方法
  # 该方法返回一个字符串，表示对象的信息
  def __str__(self):
    return f"Person(name={self.name}, age={self.age})"
  
  # 
  def __repr__(self):
    # 该方法返回一个字符串，表示对象的信息
    # 该字符串可以被eval()函数解析，得到一个与该对象相同的对象
    # 该方法的作用是方便调试
    return f"Person(name={self.name}, age={self.age})"
  
  def __delitem__(self):
    # 删除对象时，会调用该方法
    print("删除对象")
    del self.name

  def __add__(self, other):
    # 实现两个对象相加,可以自己定义对象与对象的相加规则
    # 该方法返回一个新的对象
    return Person(f"{self.name}+{other.name}", self.age + other.age)
  
  def __sub__(self, other):
    # 实现两个对象相减,可以自己定义对象与对象的相减规则
    # 该方法返回一个新的对象
    return self.age - other.age
  
  def __iter__(self):
    # 实现对象可迭代，可以用for循环遍历对象
    # 该方法返回一个迭代器对象
    return iter([self.name, self.age])

# 创建对象
p = Person("Alice", 25)

# 打印对象
print(p)

# 调用__repr__方法
print(repr(p))

# 调用__delitem__方法
# del p.name
# 再次打印对象  
# print(p) 'Person' object has no attribute 'name'

# 调用__add__方法
p2 = Person("Bob", 30)
p3 = p + p2#这里的+号调用的是__add__方法
print(p3)

# 调用__sub__方法
print(p2 - p)

# 调用__iter__方法
print(type(p))
for item in p:
  print(item)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 11.比较常用的魔术方法

```python
class Images:

  def __init__(self,path):
    self.path = path
    self.arr = ["6.jpg","5.jpg","4.jpg","3.jpg","2.jpg","1.jpg"]

  def __len__(self):
    return len(self.arr)#由自己决定的返回

  def __getitem__(self,index):
    print(index)
    return self.arr[index]#利用传入的下标进行操作
  
  def __setitem__(self,index,value):
    print(index,value)

  def __call__(self, *args, **kwargs):
    print("调用了__call__方法",args,kwargs)

  
  
  
imgs = Images("./imgs")
count = len(imgs)
print(count)#自动调用__len__

# 调用__getitem__
# print(imgs[100]) 报错，arr越界了
print(imgs[2])

# 调用__setitem__
print("===========")
imgs[1] = 2
print("===========")
print("__setitem__",imgs[1])

# 调用__call__
imgs(1,2,3,a=1,b=2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 12.继承

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

    def eat(self):
        print(f"{self.name}今年{self.age}岁，正在吃饭")
  
p1 = Person("张三", 20)
p1.eat()

class Student(Person):
    # 子类构造函数中必须调用父类构造函数
    # 否则无法调用父类属性
    def __init__(self, name, age, school):
        # 调用父类构造函数
        # 必须在子类构造函数的第一行调用
        super().__init__(name, age)
        self.school = school

s1 = Student("李四", 21, "清华大学")
s1.eat()
print(s1.school)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

张三今年20岁，正在吃饭
 李四今年21岁，正在吃饭
 清华大学

## 13.覆盖-重写

父类已经定义了一个方法，子类要将这个方法重新修改，就叫重写

```python
class Animal:
  def __init__(self,name):
    self.name = name
  
  def eat(self):
    print("Animal的eat方法，{} is eating".format(self.name))

  def sleep(self):
    print("Animal的sleep方法，{} is sleeping".format(self.name))

class Dog(Animal):
  def __init__(self, name,age):
    super().__init__(name)
    self.age = age

  def say(self):
    print("Dog的say方法，{} is barking".format(self.name))

  def eat(self):
    print("Dog重写了Animal的eat方法，{} is eating".format(self.name))

dog = Dog("旺财", 3)
print(dog.name)
print(dog.age)
dog.sleep()
dog.say()
dog.eat()
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 14.多台

```python
class Animal:
    def eat(self):
        print("动物会吃东西")

class Dog(Animal):
    def eat(self):
        print("狗会吃骨头")

class Cat(Animal):
    def eat(self):
        print("猫会吃鱼")

def eat(animal):
    animal.eat()# 体现了多态

dog = Dog()
cat = Cat()

eat(dog) 
eat(cat)

# 看dog是否是Dog或他的父类的实例
print(isinstance(dog, Animal))
print(isinstance(dog, Dog))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 15.私有属性

不同于类属性，在属性前面加__表示只能在类中调用这个属性

```python
class Person:
    __name = 'jack'
    def __init__(self, __age):
        self.__age = __age
    def fn(self):
        print("私有属性只能在类内部访问")
        print("私有属性：", self.__name)
        print("私有属性：", self.__age)

p = Person(25)
# print(p.__name)  # 报错
# print(p.__age)  # 报错
p.fn()  # 通过实例化对象调用私有方法，可以在类内部访问私有属性和方法
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 16.重载魔术方法

下面重新定义了Python中的加减乘除，实质就是改写了底层的魔术方法

```python
class Box:
  def __init__(self, width, height):
    self.width = width
    self.height = height

  def __add__(self, other):
    return self.width + self.height + other.width + other.height
  
  def __sub__(self, other):
    return self.width - self.height - other.width - other.height
  
  def __mul__(self, other):
    return self.width * self.height * other.width * other.height
  
  def __truediv__(self, other):
    return self.width / self.height / other.width / other.height
  
  def __floordiv__(self, other):
    return self.width // self.height // other.width // other.height
  

b1 = Box(2, 3)
b2 = Box(4, 5)

print(b1 + b2)
print(b1 - b2)
print(b1 * b2)
print(b1 / b2)
print(b1 // b2)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 17.super()方法

```python
class Box:
  x = 5
  def fn(self):
      print("这是Box类的fn方法")

  def fm(self):
      print("这是Box类的fm方法")

class Box2(Box):
  # 重写父类的fn方法 
  x = 10
  def fn(self):
      super().fn()
      print("这是Box2类的fn方法")
      super().fm()
      print("这是Box2类的fm方法")

b = Box2()
b.x = 400
super(Box2, b).fn()  # 这是b对象调用父类的fn方法
# 总结：执行Box2父类的fn()函数 把b2作为第一个参数self传入进去
super(Box2, b).x
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 十六、迭代器和生成器

## 1.迭代器iter

全局函数iter 可以把一个可迭代对象转换成一个迭代器，全局函数next 他可以迭代下一次迭代器中的数据，for 循环可以连续调用next

```python
arr = [10,20,30,40,50]
iterator = iter(arr)
re1 = next(iterator)
print(re1)

re2 = next(iterator)
print(re2)

re3 = next(iterator)
print(re3)

for el in iterator:
  # 接着re3迭代
  print(el,"====================")

# re4 = next(iterator)
# print(re4)#报错，re3已经迭代完了
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

 **案例：**

实现数据加载器的底层核心源代码，有一个数据容器，里面有1000条数据，封装一个可迭代对象，这个对象迭代一次就取出这个列表的n条数据，n = 8

```python
class myData:
    def __init__(self,data):
        self.data = data
        self.index = -1
    def __iter__(self):
        return self
    def __next__(self):
        while self.index < len(self.data)//8:
          self.index += 1
          return self.data[self.index * 8:(self.index+1) * 8]

data = myData(["a", "b", "c", "d", "e", "f", "g", 
        "h", "i", "j", "k", "l", "m", "n",
        "o", "p", "q", "r", "s", "t", "u", 
        "v", "w", "x", "y", "z"])


data_loader = iter(data)
re = next(data_loader)
print(re)
re = next(data_loader)
print(re)
re = next(data_loader)
print(re)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 2.生成器yield

yield关键字在函数内部 会让函数暂时生成结果，但是函数还没有运行完毕，并且这个函数调用的代码的后面的代码会正常执行

```python
def my_gen():
    print("start")
    yield 1
    print("middle")
    yield 2
    print("end")
    yield 3

re = my_gen()
print(next(re),"===========") 
# re = my_gen()
print(next(re),"===========")
# re = my_gen()
print(next(re),"===========")
# 结束迭代
# re = my_gen()
# print(next(re),"===========")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**案例：**

实现range函数源代码

```python
def myrange(start,end,step):
    i = start - step
    while True:
      i += step
      if i >= end:
        # raise StopIteration
        break
      yield i

for el in myrange(0,11,2):
   print(el)
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 十七、异常处理

```python
try:
    arr = [100,20]
    x = arr[100]
    print(x)

except ValueError:
    print("数组类型错误",ValueError)

except IndexError as e:
    print("数组越界",e)

else:
    print("没有异常")

finally:
    print("不管有没有报错都执行finally")

print("后面的代码")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

数组越界 list index out of range
 不管有没有报错都执行finally
 后面的代码

**常见的几种except选项：**

```python
| ZeroDivisionError | 除(或取模)零 (所有数据类型)  |
| ----------------- | ---------------------------- |
| ValueError        | 传入无效的参数               |
| AssertionError    | 断言语句失败                 |
| StopIteration     | 迭代器没有更多的值           |
| IndexError        | 序列中没有此索引(index)      |
| IndentationError  | 缩进错误                     |
| OSError           | 输入/输出操作失败            |
| ImportError       | 导入模块/对象失败            |
| NameError         | 未声明/初始化对象 (没有属性) |
| AttributeError    | 对象没有这个属性             |
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**或者直接不写这个错误类型**

```python
try:
    print(3 / 0)
except:
    print("报错")
else:
    print("没错")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

报错

**主动抛出错误：**

```python
def fn():
    x = 10
    if 5<x<6:
        print(x)
    else:
        raise ValueError("x不在范围内")
try:
    fn()
except ValueError as e:
    print(e)
print("后续代码")
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

x不在范围内
 后续代码

# 十八、模块与包

```python
import model1 as m1
from model2 import area
from model2 import perimeter as peri

print(m1.is_prime(7))
print(m1.is_palindrome("racecar"))

print(area(5, 6))
print(peri(5, 6))
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

## 1. __file__和__name__

这两个全局变量保存的是字符串

```python
print(__file__)# 保存的是当前文件路径
print(__name__)# 保存当前模块名
# 当运行这个Python文件，如果是入口程序
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

**运行结果：**

d:\桌面\华清\基础语法\code\Python基础语法\21-模块与包.py
 __main__

# 十九、内置函数

```python
import random
import time
import os
if __name__ != "__main__":
    # 随机数
    # random.seed(42)
    re1 = random.random()
    print("re1",re1)
    # 随机整数
    re2 = random.randint(-5,6)
    print("re2",re2)
    # 随机取出
    arr = [1,2,3,4,5,6,7,8,9]
    re3 = random.choice(arr)
    print("re3",re3)
    # 打乱列表
    re4 = random.shuffle(arr)
    print("re4",re4)#返回None
    print(arr)

    # time 模块
    def time_fn():
        t = time.time()
        print(t)

    for i in range(3):
        time_fn()
        time.sleep(1)#每次循环时间间隔5秒
        print(time.localtime())#获取时间信息
        print(time.localtime().tm_mday)#具体到某一项
        print(time.strftime("%y年%m-%d %H:%M:%S"))#格式化时间格式

# os 模块用于操作计算机的一些东西
def os_fn():
    path = os.getcwd()#获取当前文件夹地址
    print(f"====={path}=======")
    # 绝对路径
    re = os.path.join(path,"./img","a.jpg")
    print(re)
    # 相对路径
    re1 = os.path.realpath(re)
    print(re1)
    # 创建文件夹
    os.mkdir("./code/img")


if __name__ == "__main__":
    # os模块
    os_fn()


    
```

![点击并拖拽以移动](data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)

# 总结

大纲已完结，后续会有补充
