取整
# 整除
print(3//2) #等于1
print(-3//2) #等于-2
# int函数:只会去整数部分的值,不会看小数部分
print(int(1.4)) #等于1
print(int(-1.9)) #等于-1
# ceil:向下取整 floor:向上取整 round:四舍五入,.5的情况向最近的偶数方向取整,1.5为2,3.5为3
import math
print(math.floor(1.9)) #等于1
print(math.ceil(2.1)) #等于3
print(round(2.5)) # 等于2
print(round(1.5)) # 等于2
随机数
random模块
- randint(a,b):返回a和b之间的整数,a和b必须是整数
import random
print(random.randint(1,6))
- randrange(start,stop,step):和range()一样,randrange(1,100,2)返回的是1到100之间的一个奇数,参数必须是整数
import random
print(random.randrange(1,100,2))
- choice(seq):从一个列表中返回一个值
import random
print(random.choice([1,2.2,3])) # 随机返回一个
- 3.6开始提供choices,一次从样本中随机选择几个,可重复选择,可以指定权重
import random
for i in range(10):
print(random.choices([0,1],[10,1],k=10))
- random.shuffle(list) ->None 就地打乱列表元素
import random
l = [1,2,3,4]
random.shuffle(l)
print(l)
- sample(population, k) 从样本空间或总体(序列或者集合类型)中随机取出k个不同的元素,返回 一个新的列表
import random
print(random.sample([1,2,3,4,5],2))
常用数值处理函数
-
min()、max()返回最大最小值
-
pow(x,y)等于x**y
-
math.sqrt()开方
-
type()返回值的类型、isinstance(value,str)、isinstance(value,(str,int))
type(1+True) 会把True转换成1运算
线性数据结构
定义:线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)
-
顺序表:开辟一块连续的内存存储数据
-
链表:在分散的内存空间中,通过指针指向下一个元素
列表list
列表是顺序表的一种实现,开辟连续空间,顺序存储数据,数据可以是任意类型,列表是可变的,用[]表示
初始化
- []
- list()
- list(iterable)
l=[]
l1=list()
l2=list(range(5))
l3=[1,2,"a",[1,2],("s","b")]
索引
-
正索引:从左向右,范围[0,len-1]
-
负索引:从右向左,范围[-1,-len]
-
索引不在列表或者超出都会报IndexError
-
列表通过list[index]访问元素,速度很快,因为是O(1)时间复杂度
l = list(range(10))
print(l[2])
print(l[3])
print(l[4])
print(l[10]) # IndexError: list index out of range的错误
查询
- index(value,[start,[stop]]):返回参数值的索引
value是必须输入的,后面可以是0、1、2个参数,表示起始和结束索引
l = list(range(10))
print(l.index(1))
print(l.index(3, 2))
print(l.index(4, 1, 5))
- count(value):返回参数值在列表中的个数
l = [1, 1, 2, 3, 4, 111]
print(l.count(1))
- len(list)返回列表元素个数
l = [1, 1, 2, 3, 4, 111]
print(len(l))
修改
l=[1,2,3]
l[0]=100
print(l)
增加
- append(value):尾部增加单个元素
l=[1,2,3]
l.append(4)
- insert(index,value):在指定的索引前插入值,超过上界,尾部追加,超过下界,头部添加
l=[1,2,3]
l.insert(4,0)
增加多个元素
- extend(iterable)
l=[1,2,3]
l.extend([4,44,444])
- +:list1+list2产生新的列表,原来的列表不变
l1=[1,2]
l2=[3,4]
print(l1+l2)
- *:产生多个相同元素的列表
print([1]*5)
需要注意的是,当列表的中的元素是列表时,修改其中的一个列表的值,会将所有的元素的值修改
x=[[1]] * 3 # 产生[[1],[1],[1]]的列表
x[0]=100 # x的元素将会变成[100,[1],[1]]
x=[[1]] * 3
x[0][0]=100 # 将会产生[[100],[100],[100]]
简单来说,就是在内存中开启一块内存存放[1],然后列表的元素指向[1]的地址,当修改了[1]中的值,所有列表中的值也变,因为指向同一个[1]。
删除
- remove(value)->None:从做向右查找第一个匹配的值,删除并返回None,没有找到返回ValueError错误
l = [1,2,3,4]
print(l.remove())
print(1.remove(11)) # 返回ValueError错误
- pop(index):不加索引参数默认删除最后一个索引的值并返回,加上索引参数删除对应索引的值并返回,没有找到该索引返回IndexError错误
l =[1,2,3,4]
print(l.pop())
print(l)
print(l.pop(1))
print(l)
print(l.pop(11)) # 返回IndexError错误
- clear()->返回None:情况所有元素
l = [1,2,3,4]
l.clear()
print(l) #返回None
反转列表
- reverse()->None
l = [1,2,3,4]
l.reverse()
排序
- sort(key,reverse=False:key是一个自定义的方法,reverse是否倒叙排序
l = [4,3,2,1,0]
l.reverse()
成员判断
l =[1,2,3,4]
print(1 in l) # True
print(5 in l) # False
列表判断是否相等
a = list(range(4))
b = list(range(4))
print(a == b) # 判断值是否相等,返回True
c = a # 将a的地址赋予c(存储list(range(4))的地址)
c[2] = 10 # 实际上修改了a指向列表中的值,所以a和c都改变了索引2的值
print(a) # [0,1,10,3]
print(a == b) # False
print(a == c) # True
上图是执行到c=a的时候,无论是执行c[2]=10还是a[2]=10结果都是一样,改变了同一个地址列表的值
a = list(range(4))
b = a.copy() # 创建一个新的列表赋值给b
print(a == b) # True,因为==判断就是列表中的值是否相等
a[2] = 10 # 修改的是a列表的值
print(a == b) # False,值不相等了
b = a和b = a.copy()区别就是b和a指向同一个列表还是指向不同列表的区别
a = [1, [2, 3, 4], 5]
b = a.copy() # a和b指向不同列表
print(a == b) # True 相等,因为列表中的值相等
a[2] = 10 # a = [1,[2,3,4],10]
print(a == b) # 不相等,值不同了,False
a[2] = b[2] # a和b列表值相等了
print(a == b) # True
a[1][1] = 100 # 修改了列表中元素列表中的值,a.copy()拷贝了[2,3,4]的地址值,而不是值,所以无论a[1][1]还是b[1][1]=100,都修改成[2,100,3]
print(a == b) # True [1,[2,100,4],5]
print(a) # [1,[2,100,4],5]
print(b) # [1,[2,100,4],5]
-
shadow copy:碰到引用类型只会复制地址
-
deep copy:往往会复制引用类型的值
import copy
a = [1, [2, 3], 4]
b = copy.deepcopy(a) # 这次拷贝了[2,3,4],a[1]和b[1]是2个不同的列表了
print(a == b)
a[1][1] = 100
print(a == b) # False
print(a) # [1,[2,100],4]
print(b) # [1,[2,3],4]
元祖tuple
是一组元素集合,一旦定义无法改变,如果元素是引用类型,存储的是地址值,引用类型中值是可以改变,元祖用()表示
初始化
- ()、tuple() 空元祖
- tulle(iterable)
t1 = () # 空元组
t2 = (1,) # 必须有这个逗号 t2=(1)和t2=1相等
t3 = (1,) * 5 # (1,1,1,1,1)
t4 = (1, 2, 3)
t5 = 1, 'a'
t6 = (1, 2, 3, 1, 2, 3)
t7 = tuple() # 空元组
t8 = tuple(range(5))
t9 = tuple([1,2,3])
元祖操作和list类似,因为定义后无法改变,所以无法增删改,但是元素是引用类型的话,引用类型的值是可以改变的,因为元祖存储的是引用类型的值
t1 = ([1]) * 3 # 等于[1]*3 [1,1,1],因为没加,(1,)
t1[1] = 100 # [1,100,1]
# 注意下面的例子
t2 = ([1],) * 3 #
print(t2) # ([1],[1],[1]) 注意[1]是同一个列表,改变其中一个列表将会全部修改
# t2[1] = 100 报错
t2[0][0] = 100
print(t2) # ([100],[100],[100])
字符串
是字符的序列,是不可变的。Python3起,字符串都是Unicode类型
初始化
s1 = 'string'
s2 = "string2"
s3 = '''this's a "String" '''
s4 = 'hello \n magedu.com'
s5 = r"hello \n magedu.com"
s6 = 'c:\windows\nt'
s7 = R"c:\windows\nt"
s8 = 'c:\windows\\nt'
name = 'tom'; age = 20 # python代码写在一行,使用分号隔开,不推荐
s9 = f'{name}, {age}' # 3.6支持f前缀
sql = """select * from user where name='tom' """
索引
- 字符串是序列,支持下标访问。但不可变,不可以修改元素。
sql = "select * from user where name='tom'"
print(sql[4]) # 字符串'c'
sql[4] = 'o' # 不可以
连接
-
+:字符串拼接,返回新的字符串
-
join()方法:
-
sep.join(iterable)
-
使用指定字符串作为分隔符,将可迭代对象中字符串使用这个分隔符拼接起来
-
可迭代对象必须是字符串
-
返回一个新的字符串
-
x = 'ab'
x = x + 'cd'
print(','.join(x))
print('\t'.join(x))
print('\n'.join(x))
print('-'.join(range(5))) # 不行,必须是字符串
字符查找
-
find(sub,start,end):在指定的区间[start, end),从左至右,查找子串,没找到返回-1
-
rfind(sub,start,end):在指定的区间[start, end),从右至左,查找子串sub,没找到返回-1
-
index()、rindex()和上面用法相同,但是没找到会报ValueError错误
s = 'magedu.edu'
print(s.find('edu'))
print(s.find('edu', 3))
print(s.find('edu', 4))
print(s.find('edu', 6, 9))
print(s.find('edu', 7, 20))
print(s.find('edu', 200))
s = 'magedu.edu'
print(s.rfind('edu'))
print(s.rfind('edu', 3))
print(s.rfind('edu', 4))
print(s.rfind('edu', 6, 9))
print(s.rfind('edu', 7, 20))
print(s.rfind('edu', 200))
- count(sub,start,end)-->int:从左向右返回子串在字符串中的数量
s = 'magedu.edu'
print(s.count('edu'))
print(s.count('edu', 4))
- len(str):返回字符串的字符个数
print(len("abc"))
分割
-
split(sep,maxsplit=-1)-->list
- 从左向右,sep指定分隔符,默认是空白字符作为字符串
- maxsplit指定切割的次数,-1表示遍历整个字符串
-
rsplit(sep,maxsplit=-1)-->list
- 从右向左,sep指定分隔符,默认是空白字符作为字符串
- maxsplit指定切割的次数,-1表示遍历整个字符串
-
splitlines([keepends]) -> list of strings
- 按照(\n,\r,\r\n)切割,keepends是否保留切割符
-
partition(sep) -> (head, sep, tail)
- 从左向右,遇到分隔符就分割成头、分隔符、尾
- 没找到就返回头和2个空元素的3元祖
- seq必须指定
-
rpatition(seq) -> (head,seq,tail)
- 从右向左,遇到分隔符就分割成头、分隔符、尾
- 没找到就返回头和2个空元素的3元祖
- seq必须指定
s = ','.join('abcd')
print(s.split(','))
print(s.split())
print(s.split(',', 2))
s1 = '\na b \tc\nd\n' # 注意下面3个切割的区别
print(s1.split())
print(s1.split(' '))
print(s1.split('\n'))
print(s1.split('b'))
print(s1.splitlines())
s = ','.join('abcd')
print(s.partition(','))
print(s.partition('.'))
print(s.rpartition(','))
print(s.rpartition('.'))
替换
- replace(old,new,count)->str
s = ','.join('abcd')
print(s.replace(',', ' '))
print(s.replace(',', ' ', 2))
s1 = 'www.magedu.edu'
print(s1.replace('w', 'a'))
print(s1.replace('ww', 'a'))
print(s1.replace('ww', 'w')) # 返回什么?
print(s1.replace('www', 'a'))
移除
- strip([chars]) -> str
- 在字符串两端去除指定的字符集chars中的所有字符
- 如果chars没有指定,去除两端的空白字符
- lstrip([chars]) -> str ,从左开始
- rstrip([chars]) -> str,从右开始
s = '\t\r\na b c,d\ne\n\t'
print(s.strip())
print('-' * 30)
print(s.strip('\t\n'))
print('-' * 30)
print(s.strip('\t\ne\r'))
首尾判断
- endswith(suffix[, start[, end]]) -> bool
- startswith(prefix[, start[, end]]) -> bool
s = "www.magedu.edu"
print(s.startswith('ww'))
print(s.startswith('e', 7))
print(s.startswith('e', 10))
print(s.startswith('edu', 11))
print(s.endswith('edu'))
其他函数
- upper()大写
- lower()小写
- swapcase() 交换大小写
- isalnum() -> bool 是否是字母和数字组成
- isalpha() 是否是字母
- isdecimal() 是否只包含十进制数字
- isdigit() 是否全部数字(0~9)
- isidentifier() 是不是字母和下划线开头,其他都是字母、数字、下划线
- islower() 是否都是小写
- isupper() 是否全部大写
- isspace() 是否只包含空白字符
格式化输出
字节序列
python3引入bytes、bytearray类型,bytes是不可变类型,bytearray是可变类型
编码和解码
-
编码:str=>bytes,字符串在内存中存储的字节序列的值,因为计算机只认识0和1
-
解码:bytes=>str,字节序列按照某字符集转换成字符
-
python3中默认使用unicode字符集,utf-8的编码规则。unicode和utf-8的关系:www.zhihu.com/question/23… www.ruanyifeng.com/blog/2007/1…
print("abc".encdoe()) # 缺省为utf-8编码
print("啊".encode('utf-8'))
print("啊".encode('gbk'))
print(b'abc'.decode('utf8'))
print(b'\xb0\xa1'.decode('gbk')) # 不指定gbk解码的话会出现乱码,因为默认的编码规则utf-8无法识别b'\xb0\xa1'
bytes初始化
- bytes():空字节
- bytes(int):指定几个空字节的字节序列
- bytes(str,encode):等价于str.encode()
- bytes(bytes):复制一个字节序列
a=bytes()
b=bytes(2) # b'\x00\x00'
c=bytes('abc',"utf-8")
d=bytes(b'zxc')
bytesarray初始化
bytesarray可以理解为字节序列的列表
- bytesarray():空bytesarray
- bytesarray(int):指定几个空字节的字节列表
- bytesarray(str,encode):bytearray 近似string.encode(),不过返回可变对象
- bytesarray(bytes):复制一个字节序列成bytesarray
a = bytearray()
print(a)
b = bytearray(2)
print(b)
c = bytearray('abc',"utf-8")
print(c)
d = bytearray(b'qwe')
print(d)
bytearray和list比较像,所以有很多列表的操作
- append(value):尾部添加
- insert(index,value):指定索引插入
- extend(iterable_of_int):将一个可迭代的整数集合追加到当前bytearray
- pop(index):指定去除的索引
- remove(value):找到第一个删除,找不到ValueError
- clear():清空
- reverse():反转,也可以用reversed()方法
b = bytearray()
b.append(97)
b.append(99)
b.insert(1,98)
b.extend([65,66,67])
b.remove(66)
b.pop()
b.reverse()
print(b) # 输出什么
b.clear()
切片
sequence[start:stop]
sequence[start:stop:step]
-
通过索引区间获取线性结构的一部分(list tuple str bytesarray bytes)
-
start、stop、step为整数,可以是正整数、负整数、零
-
start为0时,可以省略
-
stop为末尾时,可以省略
-
step为1时,可以省略
-
切片时,索引超过上界(右边界),就取到末尾;超过下界(左边界),取到开头
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[:])
print(x[:-1]) #
print(x[0:])
print(x[3:])
print(x[3:-1]) #
print(x[9:])
print(x[:9])
print(x[9:-1])
print(x[:100])
print(x[-100:])
print(x[4:-2])
print(x[-4:-2])
print('0123456789'[-4:8])
print(b'0123456789'[-4:8])
print(bytearray(b'0123456789')[-10:5])
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[::])
print(x[::2])
print(x[2:8:3])
print(x[:9:3])
print(x[1::3])
print(x[-10:8:2])
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x[-10:])
print(x[-5:6])
print(x[-5:-6])
print(x[6:5])
print(x[5:5])
print(x[1:9:-2])
print(x[::-2])
print(x[8::-2])
print(x[8:2:-2])
print(x[8:-10:2])
print(x[8:-10:-2])
print(x[-5:4:-1])
print(x[-5:5:-1])
切片原理
x = [0, 1, 2]
y = x[:] # 复制了x列表,但是地址值不同
print(x, y)
print(id(x), id(y))
x[0] = 100 # 不会影响y
print(x, y)
x = [[1]]
y = x[:]
print(x, y)
print(x == y)
print(id(x), id(y), x is y)
x[0][0] = 100 # x和y存储的都是[1]的地址
print(x, y) # 都是[[100]]
print(x == y)
print(x is y)
x[0] = 200 # x=[200] y=[[1]]
print(x == y) # ?
print(x, y)
切片是复制了索引区间的列表,如果有引用类型,只是会复制地址值