Python 基础总结
title: Python 基础总结
date: 2023-07-19 10:51:55
tags:
- Python
categories: - Python
cover: https://cover.png
feature: false
23
11.323
你好
你好
9
1
hello world
乘
?
[‘False’, ‘None’, ‘True’, ‘and’, ‘as’, ‘assert’, ‘async’, ‘await’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’, ‘except’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘nonlocal’, ‘not’, ‘or’, ‘pass’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’]
一个变量由三部分组成,标识(id)、类型(type)、值
张三
标识 1765751614576
类型 <class ‘str’>
值 张三
李四
1.6.1 整数类型 int
可以表示正数、负数、零。默认进制是十进制,0b 表示二进制、0o 表示八进制、0x 表示十六进制
10 <class ‘int’>
-10 <class ‘int’>
0 <class ‘int’>
十进制 118
二进制 175
八进制 126
十六进制 7855
1.6.2 浮点数类型 float
由整数和小数部分组成,存储时可能出现小数部分不精确的情况
3.1415 <class ‘float’>
3.3000000000000003
可以引入 Decimal 模块来进行精确运算
3.3
1.6.3 布尔类型 bool
True 和 False,首字母为大写
True <class ‘bool’>
False <class ‘bool’>
2
1
1.6.4 字符串类型 str
字符串又被称为不可变的字符序列,可以用单引号 、双引号 、三引号 或 来表示,单引号和双引号定义的字符串必须在一行,多引号定义的字符串可以分布在连续的多行
你好 <class ‘str’>
你好 <class ‘str’>
hello
world <class ‘str’>
hello
world <class ‘str’>
1.6.5 数据类型转换
- :将其他类型转成字符串
- :将其他类型转成整数类型
- :将其他类型转成浮点数类型
<class ‘str’> <class ‘int’>
我叫张三今年18岁
<class ‘str’> <class ‘str’> <class ‘str’>
98 <class ‘int’>
1 <class ‘int’>
23 <class ‘int’>
128.0 <class ‘float’>
1.0 <class ‘float’>
23.0 <class ‘float’>
23.2 <class ‘float’>
- :单行注释
- 或 :多行注释
- :中文编码注释说明,指定源码的文件格式
输入一个词: 你好
你好
需要注意的是,输入的值为 str 类型,要计算的话需要转成数字或浮点数类型进行计算
请输入一个加数: 10
请输入一个加数: 20
<class ‘str’> <class ‘str’>
1020
30
或者直接在输入时进行转换
请输入一个加数: 10
<class ‘int’>
2.2.1 算数运算符
- :加法
- :减法
- :乘法
- :除法
- :整除
- :取余
- :幂运算
13
7
30
3.3333333333333335
3
1
1000
当存在负数时,整除和取余运算需要额外思考一下
-3
-3
-3
3
2.2.2 赋值运算符
1、赋值顺序从右到左
7
2、支持链式赋值,变量的引用都指向同一个地址
20 140728618902920
20 140728618902920
20 140728618902920
3、支持参数赋值,进行除法运算时,会转成 float 类型,因为除法可能存在小数
40
120 <class ‘int’>
60.0 <class ‘float’>
4、支持系列解包赋值
10 <class ‘int’>
20.3 <class ‘float’>
ss <class ‘str’>
2.2.3 比较运算符
对表达式大小、真假进行比较,结果是 bool 类型。 比较的是值, 或 比较的是标识
False
True
False
True
True 140728618902600
True 140728618902600
False
True 2933228983616
False 2933230769856
True
2.2.4 布尔运算符
- :且
- :或
- :非,取反
- :是否存在
- :是否不存在
False
True
False
True
False
2.2.5 位运算符
- :位与,对应位数都是 1,结果位数才为 1,其他则为 0
- :位或,对应位数都是 0,结果位数才为 0,其他则为 1
- :左移位运算符,高位溢出舍弃,低位补 0,相当于除 2
- :右移位运算符,低位溢出舍弃,高位补 0,相当于乘 2
0
12
1
16
2.2.6 运算符优先级
先算算数运算(先乘除、后加减);然后算位运算;再算比较运算;再算布尔运算;最后赋值
- **
- *、/、//、%
- +、-
- <<、>>
- &
- |
- >、<、>=、<=、==、!=
- and
- or
- =
从上到下顺序的执行代码,中间没有任何判断和跳转,直到程序结束
- 把冰箱门打开
- 把大象放进去
- 把冰箱门关上
Python 一切皆对象,所有对象都有一个布尔值,使用内置函数 可以获取对象的布尔值
以下对象的布尔值为 False
False
False
False
False
False
False
False
False
False
False
False
False
剩下的其他所有的对象的布尔值都为 True
3.3.1 单选择
请输入取款金额: 500
余额为 500
请输入取款金额: 1200
3.3.2 双选择
请输入取款金额: 1200
余额不足
3.3.3 多选择
请输入成绩: 78
一般
请输入成绩: 67
及格
请输入成绩: 102
成绩不在范围内
3.3.4 嵌套选择
请输入购物金额: 200
你有会员吗?y/ny
八折
请输入购物金额: 150
你有会员吗?y/ny
九折
3.3.5 条件表达式
当 if 为 true 时,执行左边的,else 则执行右边的
输入第一个整数: 20
输入第二个整数: 10
20大于等于10
输入第一个整数: 10
输入第二个整数: 20
10小于20
3.3.6 pass 语句
什么都不做,只是一个占位符,用于需要写语句的地方,让编辑器不报错
用于生成一个整数序列
- :创建一个 [0, stop] 之间的整数序列,步长为 1
- :创建一个 [start, stop] 之间的整数序列,步长为 1
- :创建一个 [start, stop] 之间的整数序列,步长为 step
range(0, 10) <class ‘range’>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
False
True
[5, 6, 7, 8, 9]
[5, 7, 9]
优点:不管 range 对象表示的整数序列有多长,所有 range 对象占用的内存空间都是相同的,仅仅存储了 start、stop、step,只有当用到 range 对象的时候,才会去计算序列中的相关元素
3.5.1 while 循环
0
1
3
6
10
和为: 10
3.5.2 for-in 循环
p
y
t
h
o
n
0
1
2
3
4
不需要自定义变量可以写为
hello
hello
hello
hello
hello
3.5.3 流程控制语句
- :用于结束循环结构
- :用于结束当前循环,进入下一次循环
3.5.4 else 语句
请输入密码: 888
密码错误
请输入密码: 888
密码错误
请输入密码: 888
密码错误
你的密码已输入错误三次, 请 1 分钟再试
3.5.5 嵌套循环
* * * *
* * * *
* * * *
* * * *
嵌套循环中的 break 和 continue 只控制本层循环,不影响外层循环
变量可以存储一个元素,而列表是一个大容器,可以存储 N 多个元素,列表相当于其他语言中的数组
特点:
- 元素有序
- 索引映射唯一一个数据
- 可以存储重复数据
- 可以存储任意数据类型
- 根据需要动态分配和回收内存
- :中括号
- :内置函数
2591304603584
<class ‘list’>
[‘hello’, ‘world’, 98]
[‘hello’, ‘world’, 98]
[‘p’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’]
4.2.1 查询
1、获取单个元素
- :获取列表中指定元素的索引,元素不存在会报错
- :通过索引,获取列表中的单个元素,负数表示逆向获取
0
3
world
98
2、获取多个元素,切片操作,,任何一个参数都可以省略,步长为负数同样表示逆向获取
[‘hello’, ‘world’, 98, ‘hello’] 2507973351296 [‘hello’, ‘world’] 2507974416384
[‘hello’, ‘world’] [‘hello’, ‘world’]
[‘hello’]
[‘hello’, 98]
[‘hello’, ‘world’, 98, ‘hello’]
3、判断及遍历
- :判断是否存在
- :判断是否不存在
- :遍历 list
4.2.2 添加
- :向列表末尾添加一个元素
- :向列表末尾至少添加一个元素
- :在列表的任意位置添加一个元素
- 切片,在列表的任意位置添加至少一个元素
2271766206336
[1, 2] 2271766206336
[1, 2, [3, 4], 3, 4]
[1, 10, 2, [3, 4], 3, 4]
[1, True, False]
4.2.3 删除
- :移除一个元素,有重复元素移除第一个,移除元素不存在则报错
- :删除一个指定索引位置的元素,索引不存在则报错,不指定则删除末尾元素
- 切片,一次至少删除一个元素
- :清空列表
- :删除列表
[10, 30, 40, 50, 20]
[10, 30, 40, 50]
[10, 30, 40, 50] [30, 40]
[]
4.2.4 修改
- 为指定索引的元素赋一个新值
- 为指定的切片赋一个新值
[10, 20, 100, 40]
[10, 20, 100, 2, 3]
4.2.5 排序
- :默认从小到大排序,指定 可以进行降序排序,默认为 False
- :内置函数,用法与上同,原列表不发生改变
[10, 20, 30, 50]
[50, 30, 20, 10]
[10, 20, 30, 50]
[50, 30, 20, 10]
- :表示列表元素的表达式
- :自定义变量
- :可迭代对象
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Python 内置的数据结构之一,与列表一样是一个可变序列,以键值对的方式存储数据,但键是不可变的。字典是一个无序的序列,这里的序指的是排列顺序,即输出的顺序与输入的顺序一致
特点:
- key 不能重复,值可以重复
- 字典中的元素是无序的
- key 必须是不可变对象
- 可以根据需要动态的伸缩
- 会浪费较大的内存,是一种使用空间换时间的数据结构
- :花括号
- :内置函数
{‘张三’: 100, ‘李四’: 200}
{‘name’: ‘张三’, ‘age’: 28}
5.2.1 获取
- :获取对应键的值,键不存在则报错
- :获取对应键的值,键不存在则返回 None,并且可以通过参数设置默认返回的 value
100
100
None
99
判断与遍历
- :判断是否存在
- :判断是否不存在
- :遍历字典的 key
5.2.2 增删改
1、新增:
2、修改:
3、删除
- 删除单个 key:
- 清空字典:
- 删除字典:
{‘张三’: 100, ‘李四’: 200, ‘王五’: 300}
{‘张三’: 100, ‘李四’: 200, ‘王五’: 333}
{‘张三’: 100, ‘李四’: 200}
{}
5.2.3 获取字典视图
- :获取字典的所有 key
- :获取字典的所有 value
- :获取字典的所有 key:value 对
dict_keys([‘张三’, ‘李四’]) <class ‘dict_keys’>
[‘张三’, ‘李四’]
dict_values([100, 200]) <class ‘dict_values’>
[100, 200]
dict_items([(‘张三’, 100), (‘李四’, 200)]) <class ‘dict_items’>
[(‘张三’, 100), (‘李四’, 200)]
- :字典的键值对元素
- :自定义变量
- :内置函数,用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回这些元组组成的列表
<zip object at 0x000002AA57190C40> [(‘fruit’, 100), (‘book’, 200)]
{‘fruit’: 100, ‘book’: 200}
Python 的内置数据结构之一,是一个不可变序列
可变序列:列表、字典。可以对序列执行增、删、改操作,对象地址不发生改变
不变序列可变序:字符串、元组。没有增、删、改的操作
- :小括号,小括号可省略
- :只有一个元素时,以 结尾,小括号可省略
- :内置函数
(‘python’, 99) <class ‘tuple’>
(‘python’,) <class ‘tuple’>
(‘python’,) <class ‘tuple’>
(‘python’, ‘world’, 98) <class ‘tuple’>
在多任务环境下,同时操作对象时不需要加锁,因此,在程序中尽量使用不可变序列
需要注意的是,元组存储的是对象的引用,如果元组中对象本身是不可变对象,则不能再引用其他对象;如果对象是可变对象,则可变对象的引用不可改变,但数据可以改变
python
world
98
Python 语言提供的内置数据结构,与列表、字典一样都属于可变类型的序列,集合是没有 value 的字典
- :花括号
- :内置函数
{40, 10, 20, 30} <class ‘set’>
{10} <class ‘set’>
{0, 1, 2, 3, 4} <class ‘set’>
{1, 2, 3} <class ‘set’>
{‘h’, ‘o’, ‘n’, ‘p’, ‘y’, ‘t’} <class ‘set’>
1、判断: 或
True
False
2、新增
- :一次添加一个元素
- :一次至少添加一个元素
{40, 10, 50, 20, 30}
{2, 3, 40, ‘num’, 10, ‘age’, 80, 50, 20, 90, 28, 30}
3、删除
- :一次删除一个指定元素,不存在则报错
- :一次删除一个指定元素,不存在不报错
- :一次删除一个随机元素
- :清空集合
{2, 3, ‘num’, 40, 10, 80, 50, 20, 90, 28, 30}
{2, 3, ‘num’, 40, 10, 80, 50, 20, 90, 28, 30}
{3, ‘num’, 40, 10, 80, 50, 20, 90, 28, 30}
set()
- 是否相等,可以使用运算符 或 进行判断
- 一个集合是否是另一个集合的子集,可以调用 方法进行判断
- 一个集合是否是另一个集合的超集,可以调用 方法进行判断
- 两个集合是否没有交集,可以调用 方法进行判断
True
True
True
True
False
True
- 交集:
- 并集:
- 差集:
- 对称差集:
{20}
{20, 40, 10, 30}
{10}
{40, 30}
{40, 10, 30}
,和列表生成式类似,只是括号不同
- :表示列表元素的表达式
- :自定义变量
- :可迭代对象
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
在 Python 中字符串是基本数据类型,是一个不可变的字符序列
仅保存一份相同且不可变字符串或整数的方法,不同的值被存放在驻留池中,Python 的驻留机制对相同的字符串或整数只保留一份拷贝,后续创建相同字符串或整数时,不会开辟新空间,而是把该字符串的地址或整数赋给新创建的变量
驻留机制的几种情况,注意这里要使用 Python 的命令行进行测试结果才正确,使用 PyCharm 结果可能会出现偏差,因为 Pycharm 对字符串进行了优化处理
- 字符串的长度为 0 或 1 时
- 符合标识符的字符串
- 字符串只在编译时进行驻留,而非运行时
- [-5, 256] 之间的整数数字
- sys 的 方法强制两个字符串指向同一个对象
优缺点:
- 当需要值相同的字符串时,可以直接从驻留池里拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是比较影响性能的
- 在需要进行字符串拼接时建议使用 str 类型的 方法,而非 ,因为 方法是先计算出所有字符的长度,然后再拷贝,只 new 一次对象,效率比 要高
8.2.1 查询
- :查找子串 subStr 第一次出现的位置,不存在则报错
- :查找子串 subStr 最后一次出现的位置,不存在则报错
- :查找子串 subStr 第一次出现的位置,不存在则返回 -1
- :查找子串 subStr 最后一次出现的位置,不存在则返回 -1
3
9
3
9
-1
8.2.2 大小写转换
转换后会产生一个新的字符串对象
- :将字符串中的所有字符都转成大写字母
- :将字符串中的所有字符都转成小写字母
- :将字符串中的所有大写字母转成小写字母,小写字母转成大写字母
- :把第一个字符转成大写,其余字符转成小写
- :把每个单词的第一个字符转成大写,剩余字符转成小写
HELLO,WORLD
hello,world
HELLO,world
Hello,world
Hello,World
8.2.3 内容对齐
- :居中对齐,填充参数默认为空格,宽度小于等于原长度则返回原字符串
- :左对齐,填充参数默认为空格,宽度小于等于原长度则返回原字符串
- :右对齐,填充参数默认为空格,宽度小于等于原长度则返回原字符串
- :右对齐,填充参数为 0,宽度小于原长度则返回原字符串
hello*
hello*****
*****hello
00000hello
8.2.4 分割
返回值都是一个列表
- :从左边开始分割,默认分割字符为空格,在分割次数达到 max 之后,剩下的子串会单独作为一部分
- :从右边开始分割,其他与上同
[‘he+llo’, ‘wor+ld’, ‘pyth+on’]
[‘he’, ‘llo wor’, ‘ld pyth’, ‘on’]
[‘he’, ‘llo wor’, ‘ld pyth+on’]
[‘he+llo’, ‘wor+ld’, ‘pyth+on’]
[‘he’, ‘llo wor’, ‘ld pyth’, ‘on’]
[‘he+llo wor’, ‘ld pyth’, ‘on’]
8.2.5 判断字符串
- :判断指定的字符串是否是合法的标识符
- :判断指定的字符串是否全部由空白字符组成(回车、换行、空格、水平制表符)
- :判断指定的字符串是否全部由字母组成
- :判断指定的字符串是否全部由十进制的数字组成
- :判断指定的字符串是否全部由数字组成
- :判断指定的字符串是否全部由字母和数字组成
标识符
True
False
空白符
True
False
字母
True
False
十进制数字
False
True
数字
True
字母和数字
False
True
8.2.6 替换与合并
- :将某些子串替换为其他字符串,max 表示最大替换次数
- :将列表或元组合并成一个字符串
hexxo,worxd
hexxo,world
hello,world
helloworld
helloworld
8.2.7 比较
使用运算符 >、<、>=、<=、==、!=
比较规则:依次比较每个字符,遇到不匹配的直接返回
比较原理:两个字符进行比较时,比较的是其 original value(原始值),调用内置函数 可以得到指定字符的 original value,与内置函数 对应的是内置函数 ,调用内置函数 指定 original value 可以得到对应的字符
True
97
a
8.2.8 切片
o,world
hello
lowrd
dlrow,olleh
,world
1、 作为占位符
- :字符串
- 或 :整数,可以实现宽度
- :浮点数,可以实现精度
我叫张三, 今年18岁
99
3.142
2、 作为占位符,使用索引来表示占位,配合 方法来使用
我叫张三, 今年18岁, 张三
3.1415926
3.14
3.142
3.142
3.142
3、前面加上 来表示格式化,占位符使用
我叫张三, 今年18岁
- 编码:将字符串转换为二进制数据(bytes)
- 解码:将 bytes 类型数据转换成字符串类型
计算机 A(str 在内存中以 Unicode 表示) --> encode(str) --> byte 字节传输 --> decode --> 计算机 B
b’xc4xe3xbaxc3’
b’xe4xbdxa0xe5xa5xbd’
你好
你好
函数就是执行特定任务和完成特定功能的一段代码
优点:
- 复用代码
- 隐藏实现细节
- 提高可维护性
- 提高可读性便于调试
7
7
9.2.1 参数传递
1、实参
实际参数的值,一般是函数的调用处,如上面的 与
- 位置传参,根据参数的顺序一一对应,如
- 关键字传参,根据参数名称传递,如
2、形参
形式参数,一般是函数的定义处,如上面的
9.2.2 默认值
函数定义时可以给参数设置默认值,调用函数时未传则使用默认值,传了则使用传递的值
10 10
10 30
9.2.3 可变参数
1、位置传参
使用 定义可变的位置形参,结果为一个元组
2、关键字传参
使用 定义可变的关键词形参,结果为一个字典
(2,) <class ‘tuple’>
(2, 3, 4, 5) <class ‘tuple’>
{‘a’: 10} <class ‘dict’>
{‘a’: 20, ‘b’: 30, ‘c’: 40} <class ‘dict’>
注意:相同类型的可变参数只能存在一个,同时存在可变的位置形参和可变的关键词形参时,位置形参要在前面
- 没有返回值,可以省略 return
- 返回值为 1 个时,直接返回原值
- 返回多个值时,返回结果为元组
([1, 3, 3, 5], [2, 4]) <class ‘tuple’>
123 <class ‘int’>
123 <class ‘str’>
即程序代码能访问该变量的区域
- 局部变量:在函数内定义并使用的变量,只在函数内部有效,局部变量使用 global 声明,这个变量就会成为全局变量
- 全局变量:函数体外定义的变量,可作用于函数内外
10 10 20
10
20
即在一个函数内部调用该函数本身,需要递归调用和递归终止条件。每递归调用一次函数,都会在栈内存分配一个栈帧,每执行完一次函数,都会释放对应的空间
- 缺点:占用内存多,效率低下
- 优点:思路和代码简单
120
- :如果 try 块中抛出异常,则执行 except 块
- :如果 try 块中抛出异常,则执行 except 块,否则执行 else 块
- :finally 块无论是否发生异常都会执行,常用来释放 try 块中申请的资源
出错了
division by zero
1.0
正常运行
出错了
division by zero
最后执行
1.0
正常运行
最后执行
使用 traceback 模块打印异常信息
类,是多个类似事物组成的群体的统称,能够帮助我们快速理解和判断事物的性质
- 数据类型
- 不同的数据类型属于不同的类
- 使用内置函数查看数据类型,
- 对象
- 不管是 100,还是 99、520 等,都是 int 类之下包含的相似的不同个例,这个个例专业术语称为实例或对象
Python 中一切皆对象
- 面向过程:事物比较简单,可以用线性的思维去解决
- 面向对象:事物比较复杂,使用简单的线性思维无法解决
共同点:都是解决实际问题的一种思维方式
二者相辅相成,并不是对立的,解决复杂问题,通过面向对象方式便于我们从宏观上把握事物之间复杂的关系,方便我们分析整个系统;具体到微观操作,仍然使用面向过程方式来处理
使用 修饰
2443536301376
<class ‘type’>
<class ‘main.Student’>
类的组成
- 类属性
- 实例方法:普通方法
- 静态方法: 修饰
- 类方法: 修饰
对象的创建又称为类的实例化,有了实例,就可以调用类中的内容
1693665418768
<class ‘main.Student’>
<main.Student object at 0x0000018A56535E10>
吃东西
吃东西
静态方法
静态方法
类方法
类方法
张三 18
吉林
吉林
张三 18 女
show
- 封装:提高程序的安全性
- 将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度
- 在 Python 中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前面使用两个
- 继承:提高代码的复用性
- 多态:提高程序的可扩展性和可维护性
11.5.1 封装
上面提到如果不希望属性在类对象外部被访问,前面使用两个 ,但实际上还是可以通过 来进行访问
张三
[‘_Student__age’, ‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘getstate’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘name’, ‘show’]
20
11.5.2 继承
- 如果一个类没有继承任何类,则默认继承 object
- Python 支持多继承
- 定义子类时,必须在其构造函数中调用父类的构造函数
张三 19
10001
方法重写
张三 19
10001
多继承
object 类
object 类是所有类的父类,因此所有类都有 object 类的属性和方法
- :内置函数,可以查看指定对象的所有属性
- :用于返回一个对于对象的描述,对应于内置函数 经常用于 方法,我们查看对象的信息,经常会对 方法进行重写
[‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘getstate’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘age’, ‘name’]
我的名字是张三, 今年19 岁
11.5.3 多态(静态语言和动态语言)
简单来说,多态就是具有多种形态。它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法
- 静态语言(如 Java),实现多态需要三个必要条件
- 继承
- 方法重写
- 父类引用指向子类对象
- 动态语言(如 Python),动态语言的多态崇尚“鸭子类型”
- 当看到一只鸟走起来像鸭子,游泳起来像鸭子,那么这只鸟就可以被称之为鸭子
- 在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为
猫
狗
人
- :获得类对象或实例对象所绑定的所有属性和方法的字典
- :获取对象所属的类
- :获取父类类型的元组
- :获取类的层次结构
- :获取子类类型的列表
{‘name’: ‘张三’}
{‘module’: ‘main’, ‘init’: <function C.init at 0x0000023C55F68CC0>, ‘doc’: None}
<class ‘main.C’>
(<class ‘main.A’>, <class ‘main.B’>)
(<class ‘main.C’>, <class ‘main.A’>, <class ‘main.B’>, <class ‘object’>)
[<class ‘main.C’>]
- :通过重写 方法,让内置函数 的参数可以是自定义类型
- :通过重写 方法,可以让自定义对象具有 “+”功能
- :用于创建对象
- :对创建的对象进行初始化
2
2
张三李四
创建对象过程
先执行 方法创建对象,然后将创建的对象返回,该对象即为 self,也就是实例对象,然后再执行 方法
new Student类 <class ‘main.Student’> 1978364975584
创建的对象id 1978363977808
init 创建的对象自身id 1978363977808
Student类id 1978364975584
stu1对象id 1978363977808
1、变量的赋值操作
只是形成两个变量,实际上还是指向同一个对象
<main.Cpu object at 0x000002E31C210B50>
<main.Cpu object at 0x000002E31C210B50>
2、浅拷贝
Python 拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象
<main.Computer object at 0x000002016406A290> <main.Cpu object at 0x000002016406A210> <main.Disk object at 0x000002016406A250>
<main.Computer object at 0x000002016406A350> <main.Cpu object at 0x000002016406A210> <main.Disk object at 0x000002016406A250>
3、深拷贝
使用 copy 模块的 函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
<main.Computer object at 0x000002D3219EA310> <main.Cpu object at 0x000002D3219EA290> <main.Disk object at 0x000002D3219EA2D0>
<main.Computer object at 0x000002D3219EA350> <main.Cpu object at 0x000002D3219EA410> <main.Disk object at 0x000002D3219EA490>
模块,英文为 Module,在 Python 中一个扩展名为 的文件就是一个模块
优点:
- 方便其他程序和脚本的导入并使用
- 避免函数名和变量名冲突
- 提高代码的可维护性
- 提高代码的可复用性
1、全部引入
文件
在另一个文件中引入
basic fun
张三 18
2、部分引入
basic fun
在每个模块的定义中都包括一个记录模块名称的变量 ,程序可以检查该变量,以确定他们在哪个模块中执行,如果一个模块不是被导入到其他程序中执行,那么它可能在解释器的顶级模块中执行,顶级模块的 变量的值为
文件
另一个文件中引入
30
300
此时会输出 30、300,而这里的 30 是 文件输出的,此时我们运行的是另一个文件, 文件只是作为引入其 函数,不应该执行其他代码,因此加上判断,修改如下
此时输出只为 300
Python 中的包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录
作用:
- 代码规范
- 避免模块名称冲突
包和目录的区别:
- 包含 文件的目录称为包
- 目录里通常不包含 文件
如包结构如下
其他文件引入
10
78
28
28
24
104
1690177727.869666
time.struct_time(tm_year=2023, tm_mon=7, tm_mday=24, tm_hour=13, tm_min=48, tm_sec=47, tm_wday=0, tm_yday=205, tm_isdst=0)
time.struct_time(tm_year=2023, tm_mon=7, tm_mday=24, tm_hour=13, tm_min=48, tm_sec=47, tm_wday=0, tm_yday=205, tm_isdst=0)
3.141592653589793
1、安装
,schedule 为一个任务调度模块
2、使用
hello
hello
hello
…
Python 解释器使用的是 Unicode(内存), 文件在磁盘上使用 UTF-8 存储(外存)
:指定文件格式
文件的读写俗称 “IO 操作”,首先 文件在解释器上运行,当涉及到读写文件等操作系统的资源时,解释器会调用 OS,即操作系统,然后 OS 再去操作磁盘
内置函数 创建文件对象,
- :被创建的文件对象
- :创建文件对象的函数
- :要创建或打开的文件名称
- :打开模式,默认为只读
- :值为 0,则表示不会有寄存,值为 1,访问文件时会寄存行;值大于 1,表明这就是寄存区的缓冲大小;如果取负值,寄存区的缓冲大小则为系统默认
- :文本文件中字符的编码格式,默认为 GBK
文件,编码为 UTF-8
对应读取文件也要设置编码格式为 UTF-8
[‘你好 ’, ‘Python’]
13.2.1 常用的文件打开模式
按文件中数据的组织形式,文件分为以下两大类
- 文本文件:存储的是普通“字符”文本,默认为 Unicode 字符集,可以使用记事本程序打开
- 二进制文件:把数据内容用“字节”进行存储,无法用记事本打开,必须使用专用的软件打开,如 MP3 音频文件、JPG 图片、doc 文档等
追加内容
此时 文件内容为
13.2.2 文件对象常用方法
以读写模式打开文件,这里的 r 决定了文件指针的初始位置
os 模块是 Python 内置的与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上运行,得到的结果可能不一样
os 模块与 os.path 模块用于对目录或文件进行操作
D:DevelopToolsProjectfan-leaning-pythonfanfile
[‘a.txt’, ‘open.py’, ‘system.py’, ‘write.py’]
D:DevelopToolsProjectfan-leaning-pythonfanfilesystem.py
True
(‘system’, ‘.py’)
system.py
.D:DevelopToolsProjectfan-leaning-pythonfanfile
False
True
D:DevelopToolsProjectfan-leaning-pythonfanfile
[‘walk’]
[‘a.txt’, ‘open.py’, ‘system.py’, ‘walk.py’, ‘write.py’]
D:DevelopToolsProjectfan-leaning-pythonfanfilewalk
[]
[‘walk.py’]
为了能够确定网络数据接收方和发送方是哪台电脑,需要用 IP 地址在逻辑上来唯一标记一台电脑(不能重复)
- dest ip:目标地址
- src ip:来源地址
- content:数据
14.1.1 IP 地址的版本
- IPV4:如 ,几乎全世界都是这样的地址,但是已经用光了,如果有新兴国家需要一些 IPV4 地址,无法分配
- IPV6:如 ,为了解决 IPV4 用完而提出的新的 IP 地址,几乎无穷无尽,用的设备比较少
14.1.2 IPV4 的分类
14.1.2.1 按照基本格式划分
IPV4 由 4 个字节组成,1 个字节为 8 位,则十进制数的范围为 0 ~ 255,中间由 连接,完整二进制表示为
四组数又分为两部分,一个为网络号,一个为主机号
-
A 类地址:由 1 字节的网络地址和 3 字节的主机地址组成,且网络地址的最高位为 “0”,也就是说网络号为 7 位,主机号为 24 位
地址范围为:
可用的 A 类网络有 126 个,每个网络能容纳 1677214 个主机
-
B 类地址:由 2 字节的网络地址和 2 字节的主机地址组成,且网络地址的最高位为 “10”,也就是说网络号为 14 位,主机号为 16 位
地址范围为:
可用的 B 类网络有 16384 个,每个网络能容纳 65534 个主机
-
C 类地址:由 3 字节的网络地址和 1 字节的主机地址组成,且网络地址的最高位为 “110”,也就是说网络号为 21 位,主机号为 8 位
地址范围为:
可用的 C 类网络有 2097152 个,每个网络能容纳 254 个主机
-
D 类地址:该类地址不区分网络号和主机号,因为它并不指向特定的网络,是一个专门保留的地址,第一个字节以 “1110”开头,地址范围为:,目前该类地址被用于多点广播(Multicast)中,多点广播又分为如下几类:
- 单播:一对一
- 多播:部分
- 广播:全体
-
E 类地址:该类地址同样不区分网络号和主机号,为将来使用保留,仅做实验和开发使用,以 “1111”开头
主要区别就是网络号与主机号的范围不同,一般来说 C 类地址比较常用
14.1.2.2 按照功能用途划分
-
公有地址:通俗解释:能直接上网的 IP 地址
-
私有地址:通俗解释:不能上互联网的 IP 地址叫做私有地址,即局域网,范围为
- A 类:
- B 类:
- C 类:
14.1.2.3 环回地址
范围为:,用于回路测试,能 ping 通 表示电脑具备网络功能,反之则表示不具备网络功能
IP 地址只能标记一台电脑,但是无法标识给电脑上的哪一个进程,如果一个在运行中的程序需要收发网络数据,那么就需要一个“端口”
- dest ip:目标地址
- dest port:目标端口
- src ip:来源地址
- src port:来源端口
- content:数据
在 Linux 系统中,端口有 65536(2 ^ 16)个,为了统一管理,所以进行了编号,这就是端口号
端口是由端口号来标记的,端口号只有整数,范围是 0 - 65535,不同的 Linux 系统端口数可能不一样
14.2.1 端口是怎么分配的?
端口号不是随意使用的,而是按照一定的规定进行分配,端口的分类标准有好几种,这里介绍一下知名端口和动态端口
14.2.1.1 知名端口
知名端口是众所周知的端口号,即用于特殊的程序,不能给普通程序使用,范围从 0 - 1023
- 21 端口分配给 FTP 服务
- 22 端口分配给 SSH 服务
- 80 端口分配给 HTTP 服务
- …
14.2.1.2 动态端口
动态端口的范围是 1024 - 65535,之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配
当一个系统应用程序需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用,当程序关闭,同时也就释放了所占用的端口号
14.2.2 查看端口
可见:Windows 及 Linux 常用命令总结
程序如果想要通过网络进行收发数据,除了上面的 IP 地址和端口外,还需要“网络协议”,可以理解为怎样发送数据、怎样接收数据的规范
- udp:用户数据报协议,只负责发送,不管是否成功被接收
- tcp:传输控制协议,每发送一个数据,接收方需要回送一个响应表示收到了
使用 socket 编程进行实现
14.3.1 UDP
14.3.1.1 发送数据
-
创建 socket
-
绑定来源(服务)地址和端口,即发送方的本机 IP 地址
IP 地址可以写死,但推荐置空,这样 Python 会默认去获取本机 IP 地址;也可以不绑定,这样的话 IP 同样会去获取,但端口会绑定一个随机的端口
-
使用 socket 的 方法发送数据,需要指定目标地址的 IP 和端口,这里使用 UTF-8 进行编码
14.3.1.2 接收数据
- 创建 socket
- 绑定目标 IP 地址和端口(即发送数据时的目标 IP 地址和端口),对接收方来说就是本机 IP 地址。IP 置空会默认去获取本机 IP
- 使用 socket 的 方法接收数据,接收到的数据是一个元组,该元组包含了发送过来的数据,来源 IP 地址和端口,获取具体的发送过来的数据需要解码
(b’123’, (‘172.16.63.132’, 5701))
123
(b’xe4xbdxa0xe5xa5xbd’, (‘172.16.63.132’, 5701))
你好
14.3.1.3 UDP 广播
假设我们想给所在的局域网内的其他所有电脑上的 5701 端口发送一个相同的消息,怎么实现呢?
当然,我们可以先获取到自己本机的 IP 地址,然后得到网络号,再依次循环主机的个数,给每个主机都发送一次消息,如 IP 地址为 ,一般都是 C 类地址,则网络号为 ,那么我们循环 254 次,依次给 这个范围的所有电脑的 5701 端口发送消息
但是这样做的效率很低,如果是 B 类地址,则需要发送 65534 次,显然这种实现方式是不太合适的,那么就需要用到 UDP 广播,只需要发送一次信息,就能被所有的电脑接收
创建 socket 后,设置 socket 允许广播,然后设置目标 IP 地址为
14.3.2 网络通信的基本过程
发送方:hello --> 目标 Port, 来源 Port + hello --> 目标 IP, 来源 IP + 目标 Port, 来源 Port + hello
- 先是最原始的消息
- 然后加上目标端口和来源端口,表示从哪个程序来,要到哪个程序去
- 再加上目标 IP 和来源 IP,表示从哪个电脑来,要到哪个电脑去
接收方:目标 IP, 来源 IP + 目标 Port, 来源 Port + hello --> 目标 Port, 来源 Port + hello --> hello
- 收到消息,先检测目标 IP 是不是本机
- 假如是本机,则查找目标端口是哪个程序
- 然后再将消息传递给对应的程序
14.3.3 TCP
UDP 发送数据容易丢失,而 TCP 能够保证数据稳定传送,所以更多的时候用的是 TCP,例如浏览器底层实现用的就是 TCP
14.3.3.1 特点
1、面向连接
- 通信双方必须先建立连接才能进行数据的传输,双方都必须为该连接分配必要的系统资源,以管理连接的状态和连接上的传输
- 双方间的数据传输可以通过这一个连接进行,完成数据交换后,双方都必须断开此链接,以释放系统资源
- 这种连接是一对一的,因此 TCP 不适用于广播的应用程序,基于广播的应用程序需要使用 UDP 协议
2、可靠传输
- TCP 采用 “发送-应答”机制
- TCP 发送的每个数据都必须得到接收方的应答才认为这个 TCP 数据传输成功
- 超时重传
- 发送端发出一个数据之后就启动定时器,如果在定时时间内没有收到应答就重新发送这个数据
- 为了保证不丢数据,就给每个数据一个序号,同时序号也保证了传送到接收端实体的包按序接收,然后接收端实体对已成功接收到的数据发回一个相应的确认(ACK),如果发送实体在合理的往返时延(RTT)内未收到确认,那么对应的数据就被假设为已丢失将会进行重传
- 错误校验
- TCP 用校验和函数来检验数据是否有错误,在发送方和接收方都要计算校验和
- 流量控制和阻塞管理
- 流量控制用来避免主机发送的过快而发送方来不及完全收下
14.3.3.2 TCP 与 UDP 的区别
- TCP 需要先建立连接
- TCP 每发送一个数据包,对方都要进行确认,保证数据准确到达对方,但这个确认操作不需要应用程序来做,操作系统会自动来做
- 在 TCP 通信过程中,可以想象成这个虚拟的通道正在占用,不允许其他人来发送数据
- UDP 每次发送数据的时候,都需要写上接收方的 IP 和端口,而 TCP 只需要建立一次连接,之后直接发送数据即可,不再需要填写接收方的 IP 和端口
14.3.3.3 发送数据(客户端)
- 创建 TCP 套接字
- 连接对方(目标 IP、Port)
- 发送/接收数据(不需要写目标 IP、Port)
- 关闭套接字
14.3.3.4 接收数据(服务器)
- 创建 TCP 套接字
- 准备工作(绑定信息,设置被动等)
- 等待对方连接
- 接收/发送数据
- 关闭套接字
14.3.3.5 测试及注意点
分别启动服务器和客户端,当启动并成功连接后,会返回一个元组,包含了连接好的套接字和客户端信息
客户端发送消息:
请输入数据: 123
服务端返回响应消息
请输入数据: 你好
服务端返回响应消息
服务器接收消息:
<socket.socket fd=424, family=2, type=1, proto=0, laddr=(‘172.16.63.132’, 5700), raddr=(‘172.16.63.132’, 49950)> ---- (‘172.16.63.132’, 49950)
123
你好
注意点如下:
- TCP 服务器一般情况下需要绑定,否则客户端找不到这个服务器
- TCP 客户端一般不绑定,因为是主动连接服务器,所以只需要确定好服务器的 IP、Port 等信息就好,本地客户端可以随机
- TCP 服务器中通过 可以将 socket 创建出来的主动套接字变为被动的,这是做 TCP 服务器时必须要做的
- 当客户端需要连接服务器时,就需要用 进行连接, UDP 是不需要连接的而是直接发送,但是 TCP 必须先连接,只有连接成功才能通信
- 当一个 TCP 客户端连接服务器时,服务器端会有一个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
- 后的套接字是被动套接字,用来接收新的客户端的连接请求的,而 返回的新套接字是标记这个新客户端的
- 关闭 后的套接字意味着被动套接字关闭了,会导致新的客户端不能连接服务器,但是之前已经连接成功的客户端正常通信
- 关闭 返回的套接字意味着这个客户端已经服务完毕
- 当客户端的套接字调用 后,服务器端会 解堵塞,返回返回的长度为 0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线
14.4.1 TCP 连接的三次握手
1、客户端调用 时发送一个带有标号的数据,我们把建立连接时的第 1 次数据叫做 ,其中有一个数据,例如 1
2、服务器接收到这个数据,然后回送一个数据,这个数据中有两个部分,
- 是对接收到的数据的确认,此时的数据为 2
- 表示要向客户端发送的数据,例如可以是 3
3、当客户端接收到 数据之后,提取数字 3,然后加 1,变为 4,通过 数据格式发送到服务器
14.4.2 TCP 断开连接的四次挥手
客户端调用 才会让操作系统开启 TCP 的四次挥手,但只有当服务器也调用 时,才会发送第 3 次挥手的数据
1、客户端先发送一个数据包,这里有 1 个数字,例如 100,这个数据报称为
2、服务器接收到 数据包,然后将 100 提取出来,然后加 1,得到 101,通过 数据包回送给客户端
- 此时服务器的 会解堵塞,并且返回的数据长度为 0
- 如果服务器对这个已经建立的套接字调用了 ,那么就会有下面的 2 次挥手
3、服务器发送一个数据,这有 1 个数字,例如 102,这个包类型是
4、当客户端接收到服务器的 时,提取出 102,然后加 1,再用 将 103 回送给服务器
14.4.3 MSL(Maximum Segment Lifetime)
MSL 即报文最大生存时间,表示 TCP 的数据包在网络上的最大存活时间,RFC793 定义了 MSL 为 2 分钟,Linux 设置成了 30s
在第 3 次挥手时,服务器会发送给客户端一个数据包,并且等待客户端的响应,假如此时客户端响应的包丢失了并没有发送到客户端,服务器在等待一个 MSL 后会重新发送一次第 3 次挥手的包,然后再等待客户端的响应
因此,客户端会保留 2 个 MSL 的资源,在这个时间内,没有再次接收到服务器发送过来的第 3 次挥手数据,客户端才会真正的释放它的资源
1、短连接
- 建立连接 --> 数据传输 --> 关闭连接
- 建立连接 --> 数据传输 --> 关闭连接
- 建立连接 --> 数据传输 --> 关闭连接
2、长连接
- 建立连接 --> 数据传输(保持连接)–> 数据传输(保持连接) --> … --> 关闭连接
优点和缺点
- 长连接可以省去较多的 TCP 建立和关闭连接的操作,减少资源浪费,节约时间,对于频繁请求资源的客户来说,比较适用长连接
- client 和 server 之间的连接一直不关闭的话,会存在一个问题,随着客户端连接越来越多,server 早晚会有扛不住的时候,这时候 server 就需要采取一些措施,如关闭一些长时间没有读写事件发生的连接,这样可以避免一些恶意连接导致 server 端服务受损;如果条件再允许就可以以客户端机器为颗粒度,限制每个客户端的最大连接数
- 短连接对于服务器来说管理比较简单,存在的连接都是有用的连接,不需要额外的控制手段,但如果客户端请求频繁,将在 TCP 的建立和关闭操作上浪费时间和带宽
转载请注明来自石家庄天鲲化工设备有限公司 ,本文标题:《Python 基础总结》
还没有评论,来说两句吧...