PY学习笔记
- 1 注意事项:
- 2 数据类型:
- 3 容器:
- 4 基本语法:
- 5 常用函数:
- 6 值得一提的操作:
回车键:rn 而不是单一个 r 或 n
大前提:一定要注意代码的缩进量,代码一定要对齐,不然会报错
缩进:tab 反向缩进:shift + tab
注释:
井号键 # IDLE:批量注释:alt + 3,取消注释:alt + 4 VS Code:Ctrl + /
安装模块:
pip:在命令行里执行 pip install 模块名,即可自动下载模块并安装,下载速度和成功率和网络质量有关 pip show 模块名:查看某个模块的信息 pip list:列出已安装的模块
查看模块的内容:
dir(modle)
获取函数信息:
pythonhelp(function)
删除(释放内存):
del xxx
数学常量:
pi(圆周率),e(自然常数)
2 数据类型:
布尔型:只有True和False这两个值,运算符为and(与),or(或),not(非)
空值:None,None不等于0,None是一个特殊的空值
普通的数值类型:
整形:0xff、123456 长整型:无限大小的整数,最后一位为大写或小写的“L”(建议大写):0122L、-0x19323L、5192436L 浮点型:1.23e9 (1.23*10^9)、0.000012 (1.2e-5) 复数:a+bj或complex(a,b),a和b均为浮点型
字符串:
用单引号或双引号括起来的内容(可表示转义字符)
转义字符也是字符,在字符串中含有转义字符,如’acne’,则该字符串的值就是’acne’,而在print等函数中输出时,才会把’n’变为换行命令(2020/08/11)
'a bcd_e#f' (a bcd_e#f) 'I'm "OK"' (I'm "OK")
也可以直接用16进制表示:
r'u4e2du6587' (‘中文’)
注意,在引号外面加r表示引号内的字符串默认不转义:
r'abctd' (abctd) 和 'abctd' (abc d) ### 不知道为啥在直接在python3.7.4版本的shell中输入'abctd'输出是'abctd'(2020/23/07)
r'u4e2du6587' (‘中文’) 和 'u4e2du6587' ('\u4e2d\u6578')
python还支持拼接字符串:
>>> temp1 = 'test' >>> temp2 = '_exe_' >>> temp3 = 10 >>> temp4 = temp1 + temp2 + str(temp3) >>> temp4 'test_exe_10'
另外,还需注意 str 和 bytes 的区别:
-
str:在内存中以Unicode表示,一个字符对应若干个字节,要在保存在磁盘中或者在网络上传输,就要转换为以字节为单位的 bytes
-
bytes:在引号前面加上b:b'abc' (abc三个字符,但每个字符一定只占用一个字节)
>>>str1 = 'abc'
>>>str1.replace('a','A')
'Abc'
>>>str1
'abc'
>>>str2 = str1.replace('a'.'A')
>>>str1
'abc'
>>>str2 ### 对于不变对象(如下文的元组、set也可以类比理解)来说,调用对象自身的任意方法,也不会改变该对象自身的内容。
'Abc' ### 相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
3 容器:
**注意:访问容器中的元素一般都是用中括号 [] 而不是小括号 () 或大括号 {} **
列表:
一种有序的集合,可以随时增减元素,长度为元素的个数(即列表中的列表只算一个元素),空列s表的长度为0。同一个列表内可以有不同数据类型的元素,列表也可以是另一个列表的元素,这和C的结构体很相似。基本操作方法如下:
-
创建:
list = ['Michael', 'Bob', 'Tracy']
-
访问:
list[0]: 列表第1个元素 list[len(list)-1]: 列表最后一个元素 list[-1]: 列表最后一个元素 当索引超出范围时,会报一个IndexError错误
-
添加:
向 列表末尾 添加:list.append(temp) 向 指定位置 添加:list.insert(i,temp)
-
删除:
删除 指定位置 元素:list.pop(i),删除后返回被删除元素的值 删除 最后一个 元素:list.pop()
-
替换:
- list[i] = temp
-
切片: ###对元组、字典、set基本也适用,是比较常用的操作
>>> list1 = [1,2,3,4,5,6] >>> list2 = list1[0:-1] ### 复制第一个元素到最后一个元素,最后一个不包括在内 >>> list2 [1, 2, 3, 4, 5] >>> list2 = list1[:] ### 复制整个列表,浅拷贝 >>> list2 [1, 2, 3, 4, 5, 6] >>> list2 = list1[0:-0] >>> list2 [] >>> list2 = list1[1:3] ### 复制第二个到第四个元素,第四个元素不包括在内 >>> list2 [2, 3] >>> list2 = list1[0:5:2] ### 复制第一个到最后一个元素,步长为2,最后一个不包含在内 >>> list2 [1, 3, 5]
-
列表生成器:用于生成列表,在原列表地基础上生成新的列表,或批量替换列表中的元素,可以让代码更加简洁
格式 1: [exp for var in iterable] exp:表达式 var:变量 iterable:可迭代对象 执行过程: 1,先遍历可迭代对象中的元素 2,将此元素赋值给var 3,将var的值作用到exp这个表达式上 4,将表达式的结果生成一个新列表 如: >>> l1=[1,2,3,4] >>> l2=[i*i for i in l1] >>> print(l1) >>> print(l2) #[1, 2, 3, 4] #[1, 4, 9, 16] 格式 2: 2.1 [exp for var in iterable if 判断条件] ###依次替换为iterable中满足 判断条件 的元素 2.2 [exp if 判断条件 else i for i in iterable] ###依次判断,若满足 判断条件(一般也是 exp in iterable1) 则为 exp ,否则替换为另一个iterable中的元素 2.3 [iterable1[var] if var in iterable1 else var for var in iterable2] ###和2.2类似 大致执行过程: 1,遍历得到每一个元素 2,将遍历得到的元素赋值给var 3,将var的值作用到if语句上 4,如果满足条件就将满足条件的值作用到exp表达式上 5,将exp表达式的运算结果追加到新的列表 如: >>> aaa=['黑色','红色','白色','黑色'] >>> ccc=['黑色','红色'] >>> bbb=['黄色' if i in ccc else i for i in aaa] 结果: bbb:['黄色', '黄色', '白色', '黄色'] >>> aaa=['黑色','红色','白色','黑色'] >>> ccc={'黑色':'黄色','红色':'白色'} >>> bbb=[ccc[i] if i in ccc else i for i in aaa] 结果: bbb:['黄色', '白色', '白色', '黄色'] -
注意:
>>> list1 = ['Jay', 'Bob', 'Den'] >>> list2 = [['Michael', list1, 'Tracy']] ### 则此时list1和list2的长度都是3,要访问到list1中的'jay'可以写为list2[1][0],可以类比为二维数组
元组:
和列表相似,但其元素的值不可改变:
-
创建:
空元组:tuple = () 含有多个元素的元组:tuple = (1,2,3) 只含一个元素的元组:tuple = (1,) 注意,由于括号()既可以表示元组,又可以表示数学公式中的小括号,为了避免歧义,只有一个元素的元组也要加逗号, 如:(python在显示只有一个元素的元组时也会加逗号和括号)
>>>tuple = (1) >>>tuple 1 >>>tuple = (1,) >>>tuple (1,)
-
元素值“可变”的元组:
>>> list = ['Michael', 'Bob', 'Tracy'] >>> tuple = ('a','b',list) >>> tuple ('a', 'b', 'Michael', 'Bob', 'Tracy') >>> list[0] = 'Taylor' >>> tuple ('a', 'b', 'Taylor', 'Bob', 'Tracy')解释如下:可以借助C的指针理解,tuple的每一个元素都指向固定的位置,指向不可变,但占据这个位置的元素在特殊情况下(该元素为列表)值发生了改变导致了这种情况
-
另一个易错点:
>>> temp = 12 >>> tuple = (1,2,temp) >>> tuple (1, 2, 12) >>> temp = 10 >>> tuple (1, 2, 12)
此时元组tuple的值没有**“改变”**,即也不能完全按照C的指针和静态指针来理解。
字典:
使用“键-值(key-value)”存储,一个key对应一个value,字典内部存放顺序和key的顺序无关
字典值可以没有限制地取任何python对象,既可以是标准的对象,也可以是用户定义的,但键不行
通过key计算出value的内存地址(哈希算法)实现查找的功能,查找速度不会随着字典的增加而变慢(列表则是采用遍历的方法查找,速度会随着列表大小的变化而变化)(但是字典占用内存多,列表占用内存少),如:
>>> dict = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> dict['Michael']
95
>>> dict[95]
KeyError:95
即只能通过key查找value,不能倒过来
-
操作方法:
-
增加新的键-值对/修改已有的键-值对:
>>> dict[key] = value ### 以上面的dict为例 >>> dict['Jay'] = 100 >>> dict['Michael'] = 97 >>> dict['Michael'] 97 >>> dict['Jay'] 100
-
判断键-值对是否存在:
### in >>> 'Thomas' in dict False >>> 'Michael' in dict True ### dict.get(key,value1): ### 若key不存在,返回指定的value1,若value1未指定,则返回None >>> dict.get('Thomas') ### 相当于dict.get('Thomas',None),而None在交互式环境下不显示结果 >>> dict.get('Thomas',-1) -1 -
删除:
### dict.pop(key): ### 删除key,对应的value也删除 >>> dict = {'Michael': 95, 'Bob': 75, 'Tracy': 85} >>> dict.pop('Michael') 95 >>> dict {'Bob': 75, 'Tracy': 85}
-
set:
和字典类似,也是一组key的集合,但是不储存value。
要创建一个set,需要提供一个list作为输入集合,通过set(list)输入。显示顺序不代表set是有序的(和字典一样),重复元素在set中自动被过滤。
-
操作:
-
创建:set = set(list)
>>> s = set([3,1,2,3]) >>> s {1, 2, 3} -
添加:set.add(key) ### 注意,重复添加会自动过滤重复的元素
>>> s.add(4) >>> s {1, 2, 3, 4} -
删除:
-
删除元素:set.remove(key)
>>> s.remove(4) >>> s {1, 2, 3} -
删除目标set:
>>>del set
-
-
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s1 & s2
{2, 3}
>>> s1 | s2
{1, 2, 3, 4}
set和字典都不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”,如把列表放入set则会报错:
>>> list1 = [1,2,3] >>> set = set([1,list1,2] TypeError: unhashable type: 'list'
4 基本语法:
if else: if 条件1 : 逻辑体1 elif 条件2: 逻辑体2 ··· else : 逻辑体n 也可以直接地 if 变量 : ... 此时若变量值不为零,则执行if的逻辑,若为零则执行else的逻辑 for循环: for 变量 in 范围: ###‘范围’ 可以是一个变量区间,也可以是其他的比如一个列表 逻辑体 如: >>>names = ['Michael','Bob','Tracy'] >>>for name in names: print(name) Michael Bob Tracy while循环: while(条件): 逻辑体 即满足条件的情况下重复执行逻辑体,使用方法同C break: 用于退出循环,使用方法同C continue: 用于跳过本次循环,使用方法同C pass: 占位符
-
定义函数:
def fun_name(parameter1,parameter2...,parameter_n1 = base1,parameter_n2 = base2...): 逻辑体1 return result1 逻辑体2 return result2 ··· 逻辑体n return result_n1,result_n2,... return xxx -
返回值:
若无return语句,则返回值为None,return None也可以简写为return
可有多个返回值,使用时返回值按顺序给变量赋值(实际上是返回一个元组,元组的值依次为result_n1,result_n2…),如:
import math def move(x, y, step, angle=0): nx = x + step * math.cos(angle) ny = y - step * math.sin(angle) return nx, ny ### 结果如下 ### >>> x, y = move(100, 100, 60, math.pi / 6) ### >>> print(x, y) ### >>> 151.96152422706632 70.0
- 位置参数:
略(就是最普通的参数)
- 默认参数:
***必选参数***在前,***默认参数***在后,否则Python的解释器会报错
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数,如:
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s ### 结果如下 ### >>>power(5) ### >>>25 ### >>>power(5,3) ### >>>125
另外注意,***默认参数必须指向不变对象!!!***否则可能出现一些意想不到的错误,如:
def add_end(L=[]):
L.append('END')
return L
### 结果如下
### >>> add_end()
### >>> ['END']
### >>> add_end()
### >>> ['END', 'END']
### >>> add_end()
### >>> ['END', 'END', 'END']
在上面的例子中,默认参数是[],但是函数似乎每次都“记住了**“上次添加了’END’后的list”**,原因解释如下:
Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
- 可变参数:
传入参数的数量是可变的,允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此调用该函数时,可以传入任意个参数,如:
def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n return sum ### 结果如下 ### >>> calc(1, 2) ### >>> 5 ### >>> calc() ### >> 0
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:
>>> nums = [1, 2, 3] >>> calc(nums[0], nums[1], nums[2]) >>> 14
也可以前面加一个*号,把list或tuple的元素变成可变参数传进去:
>>> nums = [1, 2, 3] >>> calc(*nums) >>> 14
*nums表示把nums这个list的所有元素作为可变参数传进去。
- 关键字参数:
允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
关键参数可以扩展函数的功能。首先可以保证接收到必选参数,同时在被调用时接收到另外的参数,如:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
### >>> person('Michael', 30)
### >>> name: Michael age: 30 other: {}
### >>> person('Bob', 35, city='Beijing')
### >>> name: Bob age: 35 other: {'city': 'Beijing'}
### >>> person('Adam', 45, gender='M', job='Engineer')
### >>> name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, city=extra['city'], job=extra['job'])
>>> name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
简化的写法:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
>>> name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra表示把extra这个字典所有key-value传入到函数的**kw参数,kw将获得一个dict
kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。
- 命名关键字参数:
用于限制关键字参数的名字。和关键字参数**kw不同,命名关键字参数*需要一个特殊分隔符*,后面的参数被视为命名关键字参数,如:
### 只接受city和job作为关键字参数:
def person(name, age, *, city, job):
print(name, age, city, job)
### >>> person('Jack', 24, city='Beijing', job='Engineer')
### >>> Jack 24 Beijing Enginee
若函数定义中已有一个可变参数,后面跟着的命名关键字参数就不需要特殊分隔符*了:
def person(name, age, *args, city, job): print(name, age, args, city, job)
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:
>>> person('Jack', 24, 'Beijing', 'Engineer')
>>> TypeError: person() takes 2 positional arguments but 4 were given
原因:由于调用时缺少参数名city和job,Python解释器把这4个参数均视为位置参数,但person()函数仅接受2个位置参数。
命名关键字参数可以有缺省值,从而简化调用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
### >>> person('Jack', 24, job='Engineer')
### >>> Jack 24 Beijing Engineer
- 调用模块:
import modle import modle as xxx from modle import xxx
5 常用函数:
-
print
### print()中可以使用单引号 ' , ### 也可以使用双引号 " , ### 还可以使用三个连续的单引号,此时可以通过回车键换行输出,输出范围为两个三引号间的内容,如: >>>print('hellow') hellow >>>print("hellow") hellow >>>print('''hellow tworld''') hellow world ### 也可以通过反斜杠实现转义字符,如n、t等,同C语言类似,不过若用print(r'''...'''')等形式,则转义字符不转义 >>>print(r'''hellow,n world''') hellow,nworld ### print()还可以和C语言一样格式化输出,如 ### 用%: >>> print('a = %dtb = %d%%'%(a,b)) a = 10 b = 20% ### %%表示% >>> print('a = %.1ftb = %03d'%(a,b)) a = 10.0 b = 020 ### %d、%s、%f、%x(16进制整数)等用法和C类似, ### %03d表示占3位,左补0;%3d表示占3位,不补0 ### 用format():用传入的参数依次替换字符串内的占位符{0}、{1}... >>> print('Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)) Hello, 小明, 成绩提升了 17.1% -
input():
### 用于读取输入,返回值为字符串,如: >>> data = input('data = ') data = _ #_为输入的内容,如键盘输入10 >>> data '10' #data为字符‘10’而不是数字 ### 此时我们可以通过 int() 函数来进行转换: >>> data = int(data) 10 -
类型转换函数:
用于将其他类型变量转为指定类型变量的函数,如上面提到的int(),其他的自行baidu: int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字符串 repr(x ) 将对象 x 转换为表达式字符串 eval(str ) 用来计算在字符串中的有效Python表达式,并返回一个对象 tuple(s ) 将序列 s 转换为一个元组 list(s ) 将序列 s 转换为一个列表 chr(x ) 将一个整数转换为一个字符 unichr(x ) 将一个整数转换为Unicode字符 ord(x ) 将一个字符转换为它的整数值 hex(x ) 将一个整数转换为一个十六进制字符串 oct(x ) 将一个整数转换为一个八进制字符串
int(object,base=10) object:一个数字或整数字符串 base:object对应的进制,省略时默认为10 返回值:object对应的10进制数### 例子: ### 无参数: >>> int() 0 ### 16进制转10进制: >>>temp = '0xac' >>>int(temp,16) 172 ### 注意,temp为字符串,若temp为一个数,则会报错: ### TypeError: int() can't convert non-string with explicit base ### 浮点数字符串转10进制; >>> temp = '23.1314' >>> print(int(float(temp))) 23 ### 注意,print(int(temp))则会报错: ### ValueError: invalid literal for int() with base 10: '23.1314' ### 同理,非整数字符串也不能直接通过int()函数转化为整型数
-
range(temp):
生成 0~temp-1的 整数序列,常用于for循环里产生一个变量范围
-
list(temp):
### 把 temp序列 转换为一个 列表 ,如: >>> list(range(5)) [0,1,2,3,4]
-
ord()和chr():
### ord():获取字符的整数表示: >>> ord('A') 65 >>> ord('中') 20013 ### chr():将编码转换为对应的字符: >>> chr(66) ‘B’ >>> chr(25991) ‘文’ -
encode() 和 decode():
### 用于 str 和 bytes 的相互转化: ### encode(): >>> 'ABC'.encode('ascii') b'ABC' >>> '中文'.encode('utf-8') b'xe4xb8xadxe6x96x87' ### decode(): >>> b'ABC'.decode('ascii') 'ABC' >>> b'xe4xb8xadxe6x96x87'.decode('utf-8') '中文' ### 注意,由于中文无法用acsii编码,所以含有中文时可能会让encode()报错: >>> '中文'.encode('ascii') Traceback (most recent call last): File "", line 1, in UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) ### 同样地,若bytes中含有无法解码的字节时,decode()也会报错: >>> b'xe4xb8xadxff'.decode('utf-8') Traceback (most recent call last): ... UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte ### 如果bytes中只有一小部分无效的字节,可以传入errors='ignore'忽略错误的字节: >>> b'xe4xb8xadxff'.decode('utf-8', errors='ignore') '中' -
len():
### 对于str:计算str的字符数 >>>len('中文'.encode('utf-8')) 6 ### 对于bytes:计算bytes所占的字节数 >>>len(b'abd') 3 >>>len(b'xe4xb8xadxe6x96x87') 6
6 值得一提的操作:
-
列表合成字典:
-
构建字典的 2 个列表长度相同
>>> a = [1,2,3,] >>> b = ['ab','ac','ad'] >>> dict(zip(a,b)) {1: 'ab', 2: 'ac', 3: 'ad'} -
构建字典的 2 个列表长度不同(key比value多)
>>> a = [1,2,3,4] >>> c = ['aa','ss'] >>> dict(zip(a,c)) {1: 'aa', 2: 'ss'} -
构建字典的 2 个列表长度不同(key比value少)
>>> a = [1,2,3,4] >>> d = ['fa','fb','fc','fd','fe'] >>> dict(zip(a,d)) {1: 'fa', 2: 'fb', 3: 'fc', 4: 'fd'}
-
-
字典键值对反转:
>>> dict1 = {"zhangsan":'12',"lisi":'13',"wangwu":'15'} >>> dict2 = {} >>> for key,val in dict1.items(): dict2[val]=key ### 结果为:dict2 = {'12': 'zhangsan', '13': 'lisi', '15': 'wangwu'} -
以指定概率选取元素:
### 思路:random.uniform(0,1)->生成0.0到1.0之间的伪随机数,之后循环元素及其概率,计算累积概率. ### 须 some_list 的长度和 probabilities 的长度一致 且 所有元素的概率相加为1.0 import random def random_pick(some_list, probabilities): x = random.uniform(0,1) # 生成值为0到1间的伪随机数 cumulative_probability = 0.0 for item, item_probability in zip(some_list, probabilities): cumulative_probability += item_probability if x < cumulative_probability: break return item ### 如:random_pick([1,2,3,4],[0.1,0.2,0.3,0.4]) ### 当x处于0.0到0.1之间,则输出1 ### 当x处于0.1到0.3之间,则输出2 -
删除多个连续空格只保留一个:
>>>str1="ww dd ddd" >>>str2=' '.join(str1.split()) ###注意单引号间为空格(若为下划线之类的则是将多个连续空格替换为一个下划线) ### 结果: ### str:"ww dd ddd"
原理:先将字符串通过split函数变为字符数组,再用字符串的隐形转换的特性将数组转换成字符串



