原始序
断断续续的学了几遍python,每次都想系统全面的学遍,因一些原因中途时常间断自己也没坚持住,这次计划在之前的基础上查漏补缺、及时归纳,力争有所成。
初版序
曾很羡慕那些掌握编程技能的老师和同学们,羡慕他们能自己编程实现些有趣功能,于是自己花费很多时间自学C/C++/数据结构/模式设计/算法/LINUX等等。研究生几年时间也基本上都再C/C++中绕(MFC、OpenCV、PCL及源码编译等),自认为C/C++也学得不错;后来发现在LINUX中写或研究算法的人很多,我也深深着迷于SLAM、ROS、ML或DL技术,于是断断续续的开始学习LINUX、Python、SLAM、ROS、DL等,也没怎么总结提高,觉得归纳总结很有必要🙂
自己一步一步的学习看见了更广阔的世界~
2020.07.29
初版参考链接:
[1]:参考链接: docs.python.org/3.7.
参考链接: Common string operations.
[2]:参考链接: RUNOOB.COM.
再版整理序
时隔多年,如今换了工作,遇到pytorch深度学习项目,还是难以着手,将pytorch过了一遍,觉得很多还是不知道什么意思,主要是Python基础不熟,数据结构和算法没看,遂再整理学习Python。
驾驶、金融、编程等越来越觉得是每个人必备技能,每一项都是通往一个新世界的工具,唯有掌握才能看到更广阔的世界。Python确实较C++简单,易上手,逐渐已经渗透到各种领域中,爬虫、数据分析、科学计算、自动化办公、自动化运维、深度学习等等。
2024.01.19
从C/C++到Python
感觉比较好的教程:
1.【完整版168集】零基础学Python从入门到精通全套课程教学
0.Python简介
1989年圣诞节期间,荷兰人程序员吉多·范罗苏姆,为了打发无趣的圣诞节创造了Python,在1991年时候真正发布,Python(天蟒蛇的意思),名字取自英国20世纪70年代首播的电视喜剧《蒙提.派森的飞行马戏团》(Monty Python’s Flying Circus)。现在已经更新到3.0版本了,2020年1月1日官宣停止了Python2的更新。
跨平台、解释型语言、交互式语言、面向对象语言、初学者最好语言(但是我觉得学了c++再学其他就更容易了)
1.Python基本语法
1.0 Python角度理解变量及内存模型
因为之前学过C++,一直是以C里面的内存模型去理解内存及变量的,导致Python学到后面复杂对象常难以理解,从Python角度理解变量及内存模型一直没碰到较好的讲解,今天有幸碰到,遂学习补充。20240119
变量是内存中一个带标签的盒子
变量由三部分组成:
标识:表示对象所存储的内存地址,使用内置函数id(obj)来获取
类型:表示的是对象的数据类型,使用内置函数type(obj)来获取
值:表示对象所存储的具体数据,使用print(obj)可以直接将值打印输出
当多次赋值后,变量名会指向新的空间
1.1 输出print()函数
- 基本介绍
可以输出数字、字符串(示意计算机不要理解,直接照样输出)、含运算符的表达式(输出表达式的结果)
可以输出到显示器、文件(fp=open(‘D:/test.txt’,‘a+’);print(‘helloworld’,file=fp))
可以换行输出,也可以不换行输出(print(‘a’,‘b’,‘c’),使用逗号分隔,同一行输出) - 语法
print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout)
objects – 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
sep – 用来间隔多个对象,默认值是一个空格。
end – 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。
file – 要写入的文件对象。
- 格式化输出
print(‘The length of %s is %d’ % (s,x))
和C语言的区别在于,Python中格式控制符和转换说明符用%分隔,后面用括号,而C语言中用逗号。 - 宽度与精度控制
print(‘%10.3f’ % PI) #字段宽10,精度3
输出: 3.142
精度为3,所以只显示142,指定宽度为10,所以在左边需要补充5个空格,以达到10位的宽度
print(‘%-10.3f’ % PI) # 3.142 #左对齐,还是10个字符,但空格显示在右边。
转换标志:-表示左对齐;+表示在数值前要加上正负号;" "(空白字符)表示正数之前保留空格();0表示转换值若位数不够则用0填充。
print(‘%+f’ % PI) #显示正负号 #+3.141593
类型f的默认精度为6位小数。
print(‘%010.3f’ % PI) #字段宽度为10,精度为3,不足处用0填充空白
000003.142 0表示转换值若位数不够则用0填充
%s 字符串采用str()的显示
%x 十六进制整数
%r 字符串(repr())的显示
%e 指数(基底写e)
%c 单个字符
%E 指数(基底写E)
%b 二进制整数
%f,%F 浮点数
%d 十进制整数
%g 指数(e)或浮点数(根据显示长度)
%i 十进制整数
%G 指数(E)或浮点数(根据显示长度)
%o 八进制整数
%% 字符%
- join()函数
将一个包含多个字符串的可迭代对象,转为用分隔符s连接的字符(不能是数字)
a = [“he”, “l”, “l”, “o”]
print(" ".join(a))
输出:he l l o(注意最后没有空格)
- fomat()函数
1.通过位置来填充字符串
print('hello {0} i am {1}'.format('world','python'))
# 输入结果:hello world i am python
print('hello {} i am {}'.format('world','python') )
# 输入结果:hello world i am python
print('hello {0} i am {1} . a now language-- {1}'.format('world','python')
# 输出结果:hello world i am python . a now language-- python
foramt会把参数按位置顺序来填充到字符串中,第一个参数是0,然后1 ……
也可以不输入数字,这样也会按顺序来填充
同一个参数可以填充多次,这个是format比%先进的地方
2.通过key来填充
obj = 'world'
name = 'python'
print('hello, {obj} ,i am {name}'.format(obj = obj,name = name))
# 输入结果:hello, world ,i am python
3.通过列表填充
list=['world','python']
print('hello {names[0]} i am {names[1]}'.format(names=list))
# 输出结果:hello world i am python
print('hello {0[0]} i am {0[1]}'.format(list))
# 输出结果:hello world i am python
4.通过字典填充
dict={‘obj’:’world’,’name’:’python’}
print(‘hello {names[obj]} i am {names[name]}’.format(names=dict))
# hello world i am python
# 注意访问字典的key,不用引号的
5.通过类的属性填充
class Names():
obj='world'
name='python'
print('hello {names.obj} i am {names.name}'.format(names=Names))
# 输入结果hello world i am python
1.2 基本数据类型
1.2.1 字符串
1.2.1.0 转意字符与原字符
- 转意字符:反斜杠\
- 原字符:不希望字符串中的转义字符起作用,就使用原字符,就是在字符串之前加上"r"
或“R”,但是最后一个字符不能是一个单独的反斜线,最后可以是双反斜线。 - chr()函数:chr(010010101)
- ord()函数:ord(‘乘’)
1.2.1.1 字符串定义:[^1]
- 可以使用引号’ ,‘’,‘’’ 来创建字符串。单双引号定义的字符串不能随意换行,需要在换行时指明换行符;
- 三引号允许一个字符串跨多行,其中可以包含换行符、制表符以及其他特殊字符。三引号让程序员从引号和特殊字符串的泥潭里面解脱出来,自始至终保持一小块字符串的格式是所谓的WYSIWYG(所见即所得)格式的;
- 单字符在Python中也是作为一个字符串使用;
- 字符串中的引号可以互相嵌套,但是不能嵌套自己(例如不能在单引号中嵌套单引号,除非转义)
- 字符串操作:“+”,“*”,“[ ]”(切片),“in”,“not in”
体会:理解Python中字符串不能同理解C/C++中字符和字符串,要将其理解成一个容器、迭代器。
字符串的驻留机制
在Python中字符串是基本数据类型,是一个不可变的字符序列(元组-不可变序列)
字符串驻留:仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量
驻留机制的几种情况:
字符串长度为0或1时
s1=‘’;s2=‘’;s1 is s2 ;Out:True
(is是比较内存地址,== 是比较值)
符合标识符的字符串
字符串只在编译时进行驻留,而非运行时
解释器也可以理解成一种编译器.pyc
[-5,256]之间的整数数字
sys中intern()方法强制2个字符串指向同一个对象
Pycharm对字符串进行了优化处理
当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免频繁的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的
在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()方法是先计算出所有字符中的长度,然后再拷贝,只new一次对象,效率比+高
字符串补充点:
操作 | 说明 |
---|---|
\ | 行尾表示续行符;行中表示转义符 |
\r | 代表光标的位置 |
\b | 退格符 |
* | 重复输出字符串 |
r’ ’ | 表示原始字符串,字符串直接按照字面意思解释。 |
% | 同C语法的格式化字符串[^2] |
f’ ’ | 字面量格式化字符串。以 f 开头,后面跟着字符串,字符串中表达式用大括号 {} 括起来,它会将变量或表达式计算后的值替换进去。Python3.8版本可用=符号来拼接运算表达式与结果 |
字符串格式化方法:
方法 | 示例题 | 说明 |
---|---|---|
format( ) | vars='{}aAbBcC'.format(变量) | |
索引传参 | vars='{2}aAbBcC{1}'.format('变量0','变量1','变量2') | 变量序号相对应,从0开始 |
关键字传递参数 | vars='{a}aAbBcC{b}'.format(a='变量a',a='变量b') | |
容器类型传参 | vars='{0[0]}aAb{0[1]}BcC{0[2]}'.format(['X','X','X','X']) | 列表方法 |
data={'X':'abc','XX':'ABC'} vars='{X}abcABC{XX}'.format(**data) | 字典方法 | |
f' ' | ||
vars='xxx:{:.2f}'.format(3.14159) | 2位小数 |
字符串相关属性和方法:
分为字符串常量,字符串查找相关函数,字符检测相关函数,字符串操作相关函数
下面函数目前先列举,后期有时间再分类
方法 | 简短说明 |
---|---|
str.capitalize() | 首字母大写 |
str.center(width[, fillchar]) | 字符串居中 |
str.count(sub[, start[, end]]) | 计数 |
str.expandtabs(tabsize=8) | tab转spaces |
str.find(sub[, start[, end]]) | 查找,返回索引 |
str.rfind(sub[, start[, end]]) | |
str.index(sub[, start[, end]]) | 同上,没找到返回ValueError错误 |
str.rindex(sub[, start[, end]]) | |
str.isalnum() | 判断字符都是字母或数字 |
str.isalpha() | 判断字符都是字母 |
str.isdecimal() | 判断字符都是十进制数 |
str.isdigit() | 判断字符都是数字 |
str.isalpha() | 判断字符都是字母 |
str.islower() | 判断字符都是小写 |
str.isnumeric() | 判断字符都是数字 |
str.isspace() | 判断字符都是空格 |
str.isupper() | 判断字符都是大写 |
str.join(iterable) | 字符串连接 |
str.ljust(width[, fillchar]) | 左对齐,字符填充至width长度 |
str.rjust(width[, fillchar]) | |
str.lower() | 字符串转为小写 |
str.split(sep=None, maxsplit=-1) | 分割字符串 |
str.rsplit(sep=None, maxsplit=-1) | |
str.splitlines([keepends]) | 按照行(‘\r’, ‘\r\n’, \n’)分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符 |
str.strip([chars]) | 去掉字符串前后字符 |
str.rstrip([chars]) | |
str.lstrip([chars]) | |
str.replace(old, new[, count]) | |
str.startswith(prefix[, start[, end]]) | 检查字符串开头 |
str.swapcase() | 翻转字符串中大小写 |
str.title() | |
str.translate(table) | |
str.upper() | |
str.zfill(width) |
二进制字符串
暂时略
1.2.2 列表
变量可以存储一个元素,而列表是一个大容器,可以存储多个元素,程序可以方便的对这些数据进行整体操作。”列表相当于其他语言中的数组“。
变量存储的是一个对象的引用:
1.2.2.1 列表定义
- 创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。可用:
vars=[ ]
vars=list( )
- 列表生成式(生成列表的公式):
列表推导式: [x for x in iterable]
进行定义 - Python中有6个序列内置类型,列表、元组、字符串、Unicode字符串、buffer对象和xrange对象。序列都可以进行的操作包括索引,切片,加,乘,检查成员。(+ 号用于组合列表,* 号用于重复列表,len(),min(),max(),index(),count(),in,not in,for x in [ ])
- 列表的数据项不需要具有相同的类型,这点不能同C/C++中数组理解。
1.2.2.2 列表基本操作
可变序列类型通用操作
操作方法 | 简要说明 |
---|---|
s[i] = x | 将 s 的第 i 项替换为 x |
s[i:j] = t | 将 s 从 i 到 j 的切片替换为可迭代对象 t 的内容 |
del s[i:j] | 等同于 s[i:j] = [] |
s[i:j:k] = t | 将 s[i:j:k] 的元素替换为 t 的元素 |
del s[i:j:k] | 从列表中移除 s[i:j:k] 的元素 |
append(x) | 将 x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x]) |
clear() | 从 s 中移除所有项 (等同于 del s[:]) |
copy() | 创建 s 的浅拷贝 (等同于 s[:]) |
extend(t) 或 s += t | 用 t 的内容扩展 s (基本上等同于 s[len(s):len(s)] = t) s *= n使用 s 的内容重复 n 次来对其进行更新 |
s.insert(i, x) | 在由 i 给出的索引位置将 x 插入 s (等同于 s[i:i] = [x]) |
pop([i]) | 弹出在 i 位置上的项 |
remove(x) | 删除 第一个 等于 x 的项目,找不到X会报错 |
reverse() | 就地将列表中的元素逆序 |
enumerate() | 将一个可遍历数据对象(列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标 |
列表操作
操作 | 简要说明 |
---|---|
append(x) | 在列表的末尾添加一个元素。相当于 a[len(a):] = [x] |
extend(iterable) | 使用可迭代对象中的所有元素来扩展列表。相当于 a[len(a):] = iterable |
insert(i, x) | 在给定的位置插入一个元素。第一个参数是要插入的元素的索引,所以 a.insert(0, x) 插入列表头部, a.insert(len(a), x) 等同于 a.append(x) |
remove(x) | 移除列表中第一个值为 x 的元素。如果没有这样的元素,则抛出 ValueError 异常 |
ist.pop([i]) | 删除列表中给定位置的元素并返回它。如果没有给定位置,a.pop() 将会删除并返回列表中的最后一个元素。( 方法签名中 i 两边的方括号表示这个参数是可选的,而不是要你输入方括号。你会在 Python 参考库中经常看到这种表示方法) |
clear() | 移除列表中的所有元素。等价于del a[:] |
index(x[, start[, end]]) | 返回列表中第一个值为 x 的元素的从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常 |
count(x) | 返回元素 x 在列表中出现的次数 |
sort(key=None, reverse=False) | 对列表中的元素进行排序(参数可用于自定义排,解释请参见 sorted()) |
reverse() | 翻转列表中的元素 |
copy() | 返回列表的一个浅拷贝,等价于 a[:] |
cmp(list1, list2) | 比较两个列表的元素 |
总结
1.2.3 字典
1.2.3.1 字典定义
- 字典的键值对用冒号 : 分割,键值对间用逗号分割,字典包括在花括号 {} 中,定义方式:
vars={ }
vars=dict( )
- 字典推导式:
字典推导式: {x for x in iterable}
- 键是唯一的,若重复则后面的键值对会替换掉前面的,值不需要唯一;值可以取任何数据类型(既可以是标准的对象,也可以是用户定义的),但键必须是不可变的,如字符串,数字或元组类型
(键必须是个不可变序列,如字符串)hash生成key,(不可变序列不可以执行增删改操作)
放入字典中键的顺序与字典存储的位置不同,由放入时通过键计算hash函数计算出位置 - 字典可进行操作:key in d,key not in d;字典不能进行**+和x**操作
- zip()操作,enumerate()操作
1.2.3.2 字典操作常用方法
字典的增删改操作:
方法 | 简要说明 |
---|---|
list(d) | 以列表形式返回字典中所以键值 |
len(d) | |
d[key] | 返回键对应的值,若不存在会报KeyError错 |
d[key] = value | 设置键值对 |
del d[key] | 删除键值对,若不存在报KeyError错 |
iter(d) | 返回键值的迭代器,同iter(d.keys()) |
clear() | 清空字典 |
copy() | 浅拷贝 |
fromkeys(iterable[, value]) | 从可迭代对象中创建一个字典 |
get(key[, default]) | 返回键的值;若不存在,则返回default值,该方法不会报错 |
items() | 返回字典项(view object)((key, value) pairs) |
keys() | 字典的键view object |
values() | 字典的值view object |
pop(key[, default]) | 弹出指定键值对,若键和默认返回没设置报KeyError错 |
popitem() | 弹出键值对项,LIFO(栈)顺序 |
setdefault(key[, default]) | 键存在则返回值;键不存在则添加键key和值default并返回值default; |
update() | |
dict.has_key(key) |
字典的视图操作:
获取字典视图:
keys() 获取字典中所有key
values() 获取字典中所有value
items() 获取字典中所有key,value对
字典元素的遍历:
for item in scores
pass
字典特点:
- 键不允许重复,重复会发生覆盖
- 值可以重复
- 字典中元素是无序的,不能指定在某位置插入元素
- 键必须是不可变对象
- 字典也可以根据需要动态地伸缩
- 字典会浪费较大的内存,是一种使用空间换时间的数据结构
1.2.4 元组
元组定义
- 元组和列表非常像,都时用于存储多个数据时使用。元组使用小括号进行定义
vars=()
vars=tuple( )
元组推导式: (x for x in iterable)
- 如果元组中只有一个元素时,则必须加逗号,如
vars=(a,)
,不然就不是元组类型了 - 元组的最大特点就是值不能被改变
- 元组中元素值不允许修改,所以只能索引操作,“+”(连接组合),“x”,“in”,“not in”,“len()”,“count()”,“index()”
- 元组中元素值不允许删除,但可以使用del语句来删除整个元组
- 列表推导式生成的是列表,元组推导式生成的是生成器,关键字yield(区别return关键字)
为什么要将元组设计成不可变序列:
多任务环境下,同时操作对象时不需要加锁,因此程序中尽量使用不可变序列
注意:
元组中存储的是对象的引用。如果元组中对象是不可变对象,则不能再引用其他对象;如果元组中的对象是可变对象,则可变对象的引用不允许改变,但数据可以改变。
1.2.5 集合
集合定义
-
集合是一个无序不重复元素序列,使用大括号 { }、set()或集合推导式建集合
vars={value1,value2,value3,...}
vars=set(value1,value2)
集合推导式: {x for x in iterable}
,其功能主要用于成员检查、序列中去重、集合运算(交集,差集,并集,对称集合) -
注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
-
操作:len(),clear(),in,not in,
-
集合是可变类型序列,是没有value的字典(同字典一样键计算hash存储)
集合基本操作
方法 | 简要说明 |
---|---|
add() | 集合添加元素 |
update() | 更新添加(列表、元组、字典)元素 |
discard() | 集合移除元素,若元素不存在不会报错 |
remove() | 集合移除元素,若元素不存在报错 |
pop() | 随机弹出某个元素 |
clear() | |
copy() | |
difference() | - |
difference_update() | |
intersection() | & |
intersection_update() | |
symmetric_difference() | ^ |
symmetric_difference_update() | |
union() | | |
update() | |
isdisjoint() | 判断集合是否包含相同元素 |
issubset() | 是否为子集 |
issuperset() | 是否为超集 |
isdisjoint() | 是否相交 |
2.Python函数创建及调用
def 名([输入参数]):
函数体
[return xxx]
函数调用参数传递内存分析
在函数调用过程中,进行参数的传递:
如果是不可变对象,在函数体的修改不会影响实参的值,arg1的修改为100,不会影响n1的值;
如果是可变对象,在函数体的修改会影响到实参的值,arg2的修改,append(10),会影响到n2的值。
那么,如果要改变外部的值改怎么做呢??
函数返回值:
返回多个值,结果是元组
函数传参:
在函数调用时,将列表中的每个元素都转换为位置实参传入,列表名前加*,字典名前加**
强制关键字传参:
def fun5(a,b,*,c,d,**args) c和d强制关键字传参,**args可变关键字参数传参
def fun6(*args,**args) *args位置可变参数传参,**args可变关键字参数传参