本文是在天池学习路线中的『python数据结构』板块, 之前学习过部分, 在此记录一些易错点和不熟悉的地方. 仅作补充, 并不是全部知识点.
详细知识点的所有代码均可在我的GitHub仓库TianChi-Studying中找到.
本笔记为阿里云天池龙珠计划Python训练营的学习内容,链接为:https://tianchi.aliyun.com/specials/promotion/aicamppython;
常见的数据类型如下:
在我们的数据类型中, 有些数据类型的不可修改的, 从而没有增删改查, 修改操作基本上都是重新创建对象后赋值.
检测类型是否可变, 可以使用
id()
观察修改前后地址是否发生变化, 但更常用的是使用hash()
, 不可哈希的将会被报错, 也就是是可变类型将会报错
在list
中可以存放任意对象, 且由于存放的是对象指针, 所以即使是简单的[1,2,3]
中也存放了3个对象和3个指针.
列表可以进行如下乘法计算
x = [0] * 5
print(x, type(x)) # [0, 0, 0, 0, 0]
x[1] = 3
print(x, type(x)) # [0, 3, 0, 0, 0]
以上结果符合期望, 而看下面这个例子
x = [[0] * 3] * 4
print(x, type(x))
# [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
x[0][0] = 1
print(x, type(x))
# [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
x是将[0] * 3
这个对象复制了4遍, 所以x
列表中保存的是1个对象和4个指向该对象的指针!
那么对[0] * 3
对象进行修改的时候, 就会得到上述的结果. 这是一个小坑⚠️, 需要注意一下.
列表的浅拷贝与深拷贝是在编程时容易遇到的坑, 这里表述一下.
list1 = [1,2,[3,4],5]
list2 = list1
list3 = list1[:]
list1[0] = 999
list1[2][0] = 777
print(list2) # [999, 2, [777, 4], 5]
print(list3) # [1, 2, [777, 4], 5]
容易发现, 列表list2
, 采用直接赋值的方法, 相当于将原list1
中的所有元素对象地址直接复制过来, 那么两个列表完全等价.
而list3
是使用了切片的方法, 对列表元素的对象值进行了深拷贝, 所以未受到修改999
的影响. 但是其中的[3,4]
对象的是一个指针, 复制的依旧是指向该对象的指针, 所以修改777
的作用生效了.
除了切片, copy方法、列表推导式和
for+append
也同样的效果
也就是说, 这种深拷贝只能深拷贝一层, 更多层次的由指针指向的对象则只能浅拷贝.
那么想要进行『完全的深拷贝』, 创建一个与原对象值相同, 但毫无关系的对象, 则需要使用copy.deepcopy
方法进行拷贝.
import copy
list1 = [1,2,[3,4],5]
list2 = copy.deepcopy(list1)
list1[0] = 999
list1[2][0] = 777
print(list2) # [1, 2, [3, 4], 5]
列表的排序可以使用list.sort()
或sorted
来实现, 前者会改变列表本身, 而后者会返回一个排序后的新列表对象.
list1 = [[9,33,666], [1,44,666],[1,33,555]]
list2 = sorted(list1,key=(lambda x: x[1]))
print(list2) # 第2列升序 [[9, 33, 666], [1, 33, 555], [1, 44, 666]]
list3 = sorted(list1,key=(lambda x: [x[1],x[2]]))
print(list3) # 第2列升序, 相同按第3列升序 [[1, 33, 555], [9, 33, 666], [1, 44, 666]]
当我们想要对列表进行排序的时候, python似乎不能像c++一样定义cmp, 实现一列升序一列降序的复杂排序, 若需如此则可以进行两次排序.
我找到了, 可以使用functools.cmp_to_key
来自定义cmp进行复杂比较. 只不过这是python 2.x
版本的旧方法, 在python 3.x
中被集成到了functools
工具中.
from functools import cmp_to_key
def mycmp(a, b):
"""
按照第1列降序排序
第1列相等按照第2列升序
"""
if a[0] != b[0]:
return a[1] < b[1]
return a[0] > b[0]
list1 = [[98,88],[66,99],[77,44],[77,77]]
list2 = sorted(list1, key=cmp_to_key(mycmp))
print(list2) # [[98, 88], [66, 99], [77, 44], [77, 77]]
单个元素需要加逗号, 与括号运算符区分开.
print(8 * (8)) # 64
print(8 * (8,)) # (8, 8, 8, 8, 8, 8, 8, 8)
使用多个变量来接收元组, 多余的可以全部使用*rest
来接收, 接收后为列表形式.
t = (1, 2, 3, 4, 5, 'python')
a, b, *rest = t
print(a, b, rest) # 1 2 [3, 4, 5, 'python']
# 1 10.31 python
将字符串中的部分字符替换为另外的字符, 可以联合使用maketrans
和translate
方法, maketrans
是得到一个可供translate
使用的字符映射表, 遵循Unicode
编码.
str7 = 'this is string example....好!!!'
intab = 'aeiou好' # 被映射字符
outtab = '12345棒' # 映射字符一一对应
trantab = str7.maketrans(intab, outtab)
print(trantab) # {97: 49, 111: 52, 117: 53, 101: 50, 105: 51}
print(str7.translate(trantab)) # th3s 3s str3ng 2x1mpl2....w4w!!!
格式化操作符的一些辅助指令
符号 | 功能 |
---|---|
m.n |
m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话) |
- |
用作左对齐 |
+ |
在正数前面显示加号( + ) |
# |
在八进制数前面显示零(‘0’),在十六进制前面显示’0x’或者’0X’(取决于用的是’x’还是’X’) |
0 |
显示的数字前面填充’0’而不是默认的空格 |
下面是一些使用%
格式化的例子, 个人更喜欢使用f-string
格式化(python 3.6+), 这些指令也都可以使用.
print('%5.1f' % 27.658) # ' 27.7'
print('%.2e' % 27.658) # 2.77e+01
print('%10d' % 10) # ' 10'
print('%-10d' % 10) # '10 '
print('%+d' % 10) # +10
print('%#o' % 10) # 0o12
print('%#x' % 108) # 0x6c
print('%010d' % 5) # 0000000005
集合操作就只整理一下数学中的一些操作.
操作符 | 函数 | 作用 |
---|---|---|
a&b |
a.intersection(b) |
交集 |
a|b |
a.union(b) |
并集 |
a-b |
a.difference(b) |
差集 |
a^b |
a.symmetric_difference(b) |
异或 |
a<=b |
a.issubset(b) |
被包含 |
a>=b |
a.issuperset(b) |
包含 |
集合本身是可变的数据类型, 但是也提供了不可变的集合, 即将集合冻结, 无法进行增删改等操作.
a = frozenset('lsgogroup')
print(a)
# frozenset({'g', 's', 'p', 'r', 'u', 'o', 'l'})
这两个函数是针对可迭代对象的方法.
enumerate(sequence, [start=0])
用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列, 也就是给原本每一个元素增加一个从start
开始的索引, 一般用在for
循环当中.
b = list(enumerate(seasons, 1))
print(b)
# [(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
zip(iter1 [,iter2 [...]])
用于将可迭代的对象作为参数, 将对象中对应的元素打包成一个个元组, 然后返回由这些元组组成的对象, 可以节约内存.
返回的是一个不可打印的变量, 需要使用 list()
转换来输出列表.
如果各个迭代器的长度不一致, 则返回与列表长度与最短的对象相同.
a = [1, 2, 3]
b = ['a', 'b', 'c']
c = ['A', 'B', 'C', 'D', 'E']
zipped = zip(a, b)
print(zipped) #
print(list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c')]
zipped = zip(a, c)
print(list(zipped)) # [(1, 'A'), (2, 'B'), (3, 'C')]
反过来, 可以利用 *
号操作符, 可以将元组解压为列表.
a = [1, 2, 3]
b = ['a', 'b', 'c']
a1, a2 = zip(*zip(a, b))
print(list(a1)) # [1, 2, 3]
print(list(a2)) # ['a', 'b', 'c']
cmp
也学到了.