前言

语言:Python(python==3.9)

编译软件:VScode、PyCharm

环境:Anaconda

一、Python注释和输入输出

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

主要功能有:

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

2.对代码进行禁用

1.单行注释

1
2
3
4
# 单行注释
# 我是一个注释 不是运行的代码 写代码的时候:Ctrl+/
# print("hello")
print(123)

点击并拖拽以移动

**运行结果:**123

2.多行注释

1
2
3
4
5
6
"""
三引号
引号内代码都注释
随便写多少行
"""
print("hello")

点击并拖拽以移动

**运行结果:**hello

3.输入和输出

1
2
3
4
5
6
7
# 输出
print("打印文本")
print("打印数字:",123)
print("文本1","文本2","文本3",sep = "-")
print("文本1",end = "\n")
print("文本2",end = "123")
print("文本3",end = "\n")

点击并拖拽以移动

运行结果:

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

1
2
3
4
5
# 输入
print(123)
x = input("打印到控制台,让程序暂停,等待用户输入")
print(x)
print(456)

点击并拖拽以移动

运行结果:

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

二、变量

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

1.数值

1
2
3
a = 100
print(a)
print(100)

点击并拖拽以移动

2.字符串

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

点击并拖拽以移动

3.变量名称的要求

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

1
2
3
4
x = 123
y = "nihao"
_ = 200
print(x,y,_)

点击并拖拽以移动

变量名字必须是连续的字母,下划线,数字的组合。错误的命名方法:first name = “123”

1
firstname = "123123" #不会报错,但是不方便阅读

点击并拖拽以移动

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

1
2
1app_version = "1.1.0"
print(1app_version)

点击并拖拽以移动

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

1
True = 10

点击并拖拽以移动

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

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

点击并拖拽以移动

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

1
PI = 3.14159

点击并拖拽以移动

4.变量名命名规则

三种写法:

1.小驼峰:huaQingYuanJian

2.大驼峰:AppVersion

3.匈牙利命名法(比较常用):ai_first_class_1

三、变量的赋值与取值

1.数据直接量

1
2
3
4
x = 100
x_2 = "hello"
#取出变量中的数据并打印
print(x)

点击并拖拽以移动

2.表达式

1
2
x_3 = x
print(x_3)

点击并拖拽以移动

3.多变量一起赋值

1
2
a = b = c = 100
print(a,b,c)

点击并拖拽以移动

4.解构赋值

1
2
w,m,n = 100,10,1
print(w,m,n)

点击并拖拽以移动

5.变量的取值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

点击并拖拽以移动

四、字符串

1.字符串的写法

1
2
3
4
x_1 = "我是一个字符串"
x_2 = ""#空字符串
x_3 = " "#空格也是字符串
print(type(x_2))

点击并拖拽以移动

1
2
3
4
5
6
7
x1 = "hello"
x2 = "hi"
x3 = """三引号也可以是字符串
可以随意换行
自带换行符
"""
print(x3)

点击并拖拽以移动

运行结果:

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

2.转义字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

点击并拖拽以移动

运行结果:

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

3.字符串常用运算操作

加号:

1
2
3
4
x1 = "华清远见"
x2 = "成都分中心"
str_1 = x1 + x2
print(str)

点击并拖拽以移动

1
2
3
4
5
6
7
x3 = "我的年龄是:"
x4 = "18"
str_2 = x3 + x4#只能字符串和字符串进行连接,两个变量的类型不匹配则不能拼接
print(str_2)

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

点击并拖拽以移动

乘号:

1
2
3
4
# 乘号
x6 = "abc"
str_3 = x6*3
print(str_3)

点击并拖拽以移动

运行结果:

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

等号:(严格区分大小写)

1
2
3
x1 = "abc"
x2 = "Abc"
print(x1==x2)

点击并拖拽以移动

运行结果:

False

4.访问子串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)

点击并拖拽以移动

运行结果:



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

心中分都成

比较常用的三个:

1
2
3
4
5
6
7
8
xx__71 = x7[::-1]
print(xx__71)

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

xx__73 = x7[-1]
print(xx__73)

点击并拖拽以移动

运行结果:

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

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

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

点击并拖拽以移动

**运行结果:**True

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

1
2
3
4
5
6
x1 = "abcdefg"
x2 = "ab"
x3 = "gh"
print(x1 in x2)
print(x3 in x1)
print(x3 not in x1)

点击并拖拽以移动

运行结果:

False
False
True

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

1
2
3
x1 = "abc"
n = len(x1)
print(n)

点击并拖拽以移动

**运行结果:**3

8.常见占位符

1
2
3
4
5
6
7
8
9
10
11
12
13
占位符和类型码

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

点击并拖拽以移动

9.字符串格式化表达式

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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)

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
6
7
r = 144
g = 127
b = 255
x1 = "rgb(144,127,255)"
x2 = f"rgb({r},{g},{b})"
print(x1)
print(x2)

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 将字母全部转换为小写
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)

点击并拖拽以移动

运行结果:

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.进制

十进制

1
x = 10

点击并拖拽以移动

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

1
2
y = 0o100
print(y)

点击并拖拽以移动

十六进制

1
2
z = 0xD1BfD
print(z)

点击并拖拽以移动

二进制

1
2
m = 0b1010001
print(m)

点击并拖拽以移动

运行结果:

64
859133
81

2.浮点数与科学计数法

1
2
3
4
5
6
7
8
9
10
11
x = 1.0
y = 2.
z = .6

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

点击并拖拽以移动

3.数字类型转换

1
2
3
4
5
6
7
8
9
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)

点击并拖拽以移动

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

1
2
print(math.ceil(3.14))
print(math.floor(3.94))

点击并拖拽以移动

运行结果:

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

4.布尔类型

1
2
3
4
5
6
7
8
x = 0
print(bool(x))
y = ""
print(bool(y))
z = "0"
print(bool(z))
# 空的集合,列表,字符串都是True
print(10<20)

点击并拖拽以移动

运行结果:

False
False
True
True

5.字节串和空值

1
2
3
4
5
6
7
# 字节串
text = b"hello"
print(type(text))

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

点击并拖拽以移动

六、列表

1.字面量

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

点击并拖拽以移动

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

1
2
x = list()
print(x)

点击并拖拽以移动

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

1
2
3
4
5
x = list("hello")
print(x)
# 或者
x = list(range(10))
print(x)

点击并拖拽以移动

4.列表的运算

1
2
3
4
5
6
7
y = [4,5,6]
num = 5
z = x + y
print(z)
# 不能列表乘以列表,不能列表乘以浮点数
print(z)
z = x * num

点击并拖拽以移动

5.in / not in

1
2
3
x = ["a","b","c"]
print("a" in x)
print("b" not in x)

点击并拖拽以移动

6.列表切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

点击并拖拽以移动

运行结果:

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

7.列表的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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)))

点击并拖拽以移动

运行结果:

[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.创建元组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

点击并拖拽以移动

运行结果:

(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.元组的操作

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

点击并拖拽以移动

3.解构赋值

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

1
2
x1,x2 = (10,20)
print(x1,x2)

点击并拖拽以移动

4.元组的运算

1
2
3
4
x = (10,20)
y = (30,40)
print(x+y)
print(x * 3)

点击并拖拽以移动

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

1
2
3
4
5
6
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)

点击并拖拽以移动

八、字典

1.创建空字典

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

点击并拖拽以移动

运行结果:

{}
{‘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.字典的操作

1
2
3
4
5
6
7
# 添加和修改和访问
title = {"name":"jack","age":18,"home":"beijing"}
title["age"] = 20
print(title)
title["school"]="swust"
print(title)
print(title["home"])

点击并拖拽以移动

运行结果:

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

3.in/not in

只能用来判断键

1
2
3
title = {"name":"jack","age":18,"home":"beijing"}
print("name" in title)
print("jack" in title)

点击并拖拽以移动

运行结果:

True
False

4.删除字典

1
2
3
4
5
6
title = {"name":"jack","age":18,"home":"beijing"}
del title["name"]
print(title)
title.clear()
print(title)
del title

点击并拖拽以移动

运行结果:

{‘age’: 18, ‘home’: ‘beijing’}
{}

5.常见API

1
2
3
title = {"name":"jack","age":18,"home":"beijing"}
print(len(title))
print(type(title))

点击并拖拽以移动

运行结果:
3
<class ‘dict’>

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

1
2
str1 = str(title)
print(str1,type(str1))

点击并拖拽以移动

运行结果:
{‘name’: ‘jack’, ‘age’: 18, ‘home’: ‘beijing’} <class ‘str’>

6.字典的一些方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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)

点击并拖拽以移动

运行结果:

{}
{‘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.创建集合

1
2
3
4
5
6
7
8
9
10
11
12
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)

点击并拖拽以移动

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

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

点击并拖拽以移动

易混点

1
2
3
4
5
6
7
s5 = {(10)}

print(s5)

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

print(s6)

点击并拖拽以移动

运行结果:

{10}

{(10,)}

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

1
2
3
4
x = (10,20)
y = (10,20)
print(x==y)
print(id(x)==id(y))

点击并拖拽以移动

2.案例

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

1
2
3
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))

点击并拖拽以移动

3.固定集合

不可以更改元素

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

print(s1)

点击并拖拽以移动

4.eval()函数

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

1
2
3
4
5
6
7
8
9
str1 = "10+20"

eval(str1)

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

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

print(eval(str2))

点击并拖拽以移动

十、运算符

1.逻辑运算符

A and B

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

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

1
2
3
4
5
6
7
8
x1 = 100
x2 = 200
x3 = 0
x = x1 and x2
print(x)

x = x3 and x2
print(x)

点击并拖拽以移动

运行结果:

200
0

A or B

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

1
2
3
4
x = x1 or x2
print(x)
x = x3 or x2
print(x)

点击并拖拽以移动

运行结果:

100
200

not A

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

1
2
3
4
x = not x1
print(x)
x = not x3
print(x)

点击并拖拽以移动

运行结果:

False
True

2.位运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
x1 = 0b1010

x2 = 0b1100

# 默认输出十进制数

print(x1 & x2)#按位与

print(x1 | x2)#按位或

print(x1 ^ x2)#按位异或

print(~x1)#按位取反

点击并拖拽以移动

运行结果:

8

14

6

-11

1
2
3
4
5
6
7
x1 = x1^x2

x2 = x1^x2

x1 = x1^x2

print(x1,x2)

点击并拖拽以移动

运行结果:

12 10

左移运算符

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

1
2
3
4
5
x1 = 0b1010

x2 = 2

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

点击并拖拽以移动

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

右移运算符

1
2
3
4
5
x1 = 0b1010

x2 = 2

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

点击并拖拽以移动

运行结果:

40

2

3.身份运算符

1
2
3
4
a = 10
b = 10
print(a is b) # True
print(a is not b) # False

点击并拖拽以移动

4.成员运算符

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

点击并拖拽以移动

5.三元运算符

1
2
3
4
a = 10
b = 20
result = a if a > b else b
print(result)

点击并拖拽以移动

运行结果:

20

十一、表达式

\1. 算术表达式

\2. 逻辑表达式

\3. 关系表达式

\4. 赋值表达式

\5. 条件表达式

\6. 位运算表达式

\7. 成员运算表达式

\8. 身份运算表达式

十二、语句

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

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

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

1.if语句

1
2
3
4
5
6
7
8
9
10
11
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")

点击并拖拽以移动

2.循环语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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("永远不会结束")

点击并拖拽以移动

3.break和continue语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 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)

点击并拖拽以移动

4.推导式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 列表推导式
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)

点击并拖拽以移动

运行结果:

[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语句

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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()# 手动关闭文件

点击并拖拽以移动

十三、函数

1.声明函数

1
2
3
4
5
6
7
def f1():
print("f1运行")
f1()

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

点击并拖拽以移动

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

1
2
3
4
def f2(x1,x2):
return x1+x2
a = f2(6,6)
print(a)

点击并拖拽以移动

运行结果:

f1运行
11
12

2.参数的数量和位置

1
2
3
4
5
6
7
8
9
10
11
# 参数数量和位置一致
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

点击并拖拽以移动

3.关键字参数

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

1
2
3
4
5
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

点击并拖拽以移动

4.元组解包参数

1
2
3
4
5
6
7
8
9
10
11
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)

点击并拖拽以移动

运行结果:

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

5.字典解包参数

1
2
3
4
5
6
def fn(a,b,**args):
print(a,b)
print(args,type(args))

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

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
def my_func(*args, **kwargs):
print(args)
print(kwargs)

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

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
# 列表也可以解包
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) # 解包

点击并拖拽以移动

6.占位符

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

点击并拖拽以移动

7.匿名函数lambda

1
2
3
4
5
6
fn=lambda x,y:x+y
print(fn(2,3))

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

点击并拖拽以移动

案例1:判断是否是闰年

1
2
3
4
5
6
7
8
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))

点击并拖拽以移动

案例2:按比例划分数据集

1
2
3
4
5
6
7
8
9
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)

点击并拖拽以移动

运行结果:

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

函数分为三种:

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

8.官方内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 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')")

点击并拖拽以移动

运行结果:

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环境全局变量的名字

1
2
3
x = 10
y = 20
print(globals())

点击并拖拽以移动

运行结果是一大串字典

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

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

点击并拖拽以移动

运行结果:

{‘x’: 1, ‘y’: 2}

10.filter函数

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

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

点击并拖拽以移动

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)

点击并拖拽以移动

运行结果:

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

11.map函数

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

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

点击并拖拽以移动

实现

1
2
3
4
5
6
7
8
9
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)

点击并拖拽以移动

运行结果:

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

12.reduce函数

reduce(函数,可迭代对象,初始值)

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

1
2
3
4
5
6
7
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)

点击并拖拽以移动

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

点击并拖拽以移动

运行结果:

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

13.作用域

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

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

点击并拖拽以移动

运行结果:

20
10
30
100

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

点击并拖拽以移动

运行结果:

6

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

1
2
3
4
5
6
7
8
9
a = 100
def fm():
print(a)

def fn():
a = 200
fm()

fn()

点击并拖拽以移动

运行结果:

100

函数也是一种数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def f1():

a = 100

def f2():

print(a)

return f2

a = 200

re = f1()

re()# 执行函数

点击并拖拽以移动

作用域案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

点击并拖拽以移动

运行结果:

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

14.修改变量值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 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()

点击并拖拽以移动

运行结果:

10
20
20
20

15.内建作用域

1
print(__name__)

点击并拖拽以移动

运行结果:

main

16.递归

1
2
3
4
5
6
7
8
def f(a):
if a > 5:
return a
else:
return f(a+1)

r = f(0)
print(r)

点击并拖拽以移动

运行结果:

6

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

1
2
3
4
def fn():
return 1+1
print(type(fn))
print(type(fn()))

点击并拖拽以移动

运行结果:

<class ‘function’>
<class ‘int’>

16.回调函数 callback

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

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

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

1
2
3
4
5
6
7
8
9
10
11
# 定义两个函数
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

点击并拖拽以移动

回调函数怎么体现:

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

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

而是交给业务函数(回调)使用

1
2
3
4
5
6
7
8
9
10
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))

点击并拖拽以移动

运行结果:

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

17.闭包函数 block

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
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

点击并拖拽以移动

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 案例
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()

点击并拖拽以移动

运行结果:

666
616

十四、装饰器

参考:一文搞懂Python装饰器(通俗易懂) - 知乎

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

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

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

不带参数的装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def fn():
print("fn函数的业务是答应一句话:未来业务可能有很多行代码")


# 设计一个装饰器

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

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

fn2()

点击并拖拽以移动

运行结果:

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

带参数的装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 带参数的装饰器
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

点击并拖拽以移动

运行结果:

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

作用:

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

十五、面向对象

1.类和对象的语法

定义一个类

1
2
3
4
5
6
7
8
9
class Person:
name = "张三"
age = 18
life = 1

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

print(Person,type(Person))

点击并拖拽以移动

用这个类创造对象

1
2
p1 = Person()
print(p1,type(p1))

点击并拖拽以移动

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

语法:对象名.成员名

1
2
3
4
5
6
7
print(p1.name,p1.age,p1.life)

p1.fn(1)


p2 = Person()
p2.fn(2)

点击并拖拽以移动

运行结果:

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

2.init

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

点击并拖拽以移动

运行结果:

init name: xiaoming 年龄: 18
fn name: xiaoming 年龄: 18

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

1
2
3
4
5
6
7
8
9
10
11
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)

点击并拖拽以移动

运行结果:

boss 2000
npc 100

3.对象语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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)

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
6
7
8
9
10
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()

点击并拖拽以移动

运行结果:

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

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

1
2
3
4
5
6
7
8
9
10
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)

点击并拖拽以移动

运行结果:

486000

案例1

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

点击并拖拽以移动

运行结果:

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

案例2:

公司员工管理系统

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

\1. 定义一个 Employee 类,包含以下属性:

- name(姓名)

- position(职位)

- salary(薪水)

\2. 定义一个 Company 类,包含以下内容:

- 一个列表属性,用于存储 Employee 对象。

- 一个方法 hire_employee,用于招聘新员工。

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

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

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

\3. 测试代码:

- 创建一个 Company 对象。

- 招聘几个员工。

- 列出所有员工。

- 解雇一个员工。

- 再次列出所有员工。

- 打印公司总薪水。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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)

点击并拖拽以移动

运行结果:

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

6.类属性和类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()

点击并拖拽以移动

运行结果:

100
100
500
100
100

7.类属性和类方法

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()

点击并拖拽以移动

显式的指定类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()

点击并拖拽以移动

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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))

点击并拖拽以移动

批量创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)

点击并拖拽以移动

8.静态方法

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)

点击并拖拽以移动

9.构造方法

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

1
2
3
4
5
6
7
8
9
10
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)

点击并拖拽以移动

10.魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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)

点击并拖拽以移动

11.比较常用的魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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)

点击并拖拽以移动

12.继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)

点击并拖拽以移动

运行结果:

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

13.覆盖-重写

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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()

点击并拖拽以移动

14.多台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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))

点击并拖拽以移动

15.私有属性

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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() # 通过实例化对象调用私有方法,可以在类内部访问私有属性和方法

点击并拖拽以移动

16.重载魔术方法

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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)

点击并拖拽以移动

17.super()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

点击并拖拽以移动

十六、迭代器和生成器

1.迭代器iter

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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已经迭代完了

点击并拖拽以移动

案例:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

点击并拖拽以移动

2.生成器yield

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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),"===========")

点击并拖拽以移动

案例:

实现range函数源代码

1
2
3
4
5
6
7
8
9
10
11
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)

点击并拖拽以移动

十七、异常处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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("后面的代码")

点击并拖拽以移动

运行结果:

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

常见的几种except选项:

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

点击并拖拽以移动

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

1
2
3
4
5
6
try:
print(3 / 0)
except:
print("报错")
else:
print("没错")

点击并拖拽以移动

运行结果:

报错

主动抛出错误:

1
2
3
4
5
6
7
8
9
10
11
def fn():
x = 10
if 5<x<6:
print(x)
else:
raise ValueError("x不在范围内")
try:
fn()
except ValueError as e:
print(e)
print("后续代码")

点击并拖拽以移动

运行结果:

x不在范围内
后续代码

十八、模块与包

1
2
3
4
5
6
7
8
9
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))

点击并拖拽以移动

1. file__和__name

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

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

点击并拖拽以移动

运行结果:

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

十九、内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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()



点击并拖拽以移动

总结

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