Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
我们可以通过声明JS对象一样的方式声明dict
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
print(d['Michael']) # 95
dict快的原因在于,在内部就可以直接算出Michael
对应存放成绩的“页码”,可以直接获取对应的内存地址并取出来,所以速度非常快
你可以猜到,这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
若存入相容的key值,内容就会被重置。key对应的值就会被新设置的值给替代
二是通过dict提供的get()
方法,如果key不存在,可以返回None
,或者自己指定的value;
d = {
"name": "张三",
"age": 18,
"sex": "男",
"height": 1.75,
"weight": 70,
"address": "北京市朝阳区",
"phone": "13800138000",
"name": "张三",
}
print(d) # {'name': '张三', 'age': 18, 'sex': '男', 'height': 1.75, 'weight': 70, 'address': '北京市朝阳区', 'phone': '13800138000'}
print(d["name"]) # 张三
print(d["age"]) # 18
## 重新修改值
d["name"] = "李四" # 修改值
print(d["name"]) # 李四
print(d.get("name")) # 李四
print(d.get("name1")) # None,get方法可以获取到值,如果值不存在,则返回None,不会报错。
print(d.get("name1", "张三")) # 张三,get方法可以获取到值,如果值不存在,则返回默认值。
如果key不存在,dict就会报错:
d["test"]
Traceback (most recent call last):
File "E:\Python\Python基础\dictAndSet.py", line 21, in <module>
d["test"]
~^^^^^^^^
KeyError: 'test'
要避免key不存在的错误,有两种办法,一是通过in
判断key是否存在:
if "test" in d: # 判断键是否存在
d["test"]
print("name存在") # name存在
else:
print("name不存在")
要删除一个key,用pop(key)
方法,对应的value也会从dict中删除:
d.pop("address")
print("address" in d) # False,pop方法可以删除键值对,返回删除的值。
dict | list |
---|---|
查找和插入的速度极快,不会随着key的增加而变慢; | 查找和插入的时间随着元素的增加而增加; |
需要占用大量的内存,内存浪费多。 | 占用空间小,浪费内存很少。 |
dict是用空间来换取时间的一种方法。 dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是不可变对象。
与dict类似,也是一组key的集合,但不存储value,并且 key
不能重复。
s = {1, 1, 2, 2, 3, 3}
set有个好处,它会自动过滤掉重复元素
通过add(key) 方法,可以添加元素进set中。
通过remove(key)方法,可以删除指定的元素
s.add(4)
s.remove(2)
print(s) # 1 3 4
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作
a = {1, 2, 3, 4, 5}
b = {1, 8,10,9, 4, 5}
print(a & b) # 1 4 5 交集,取两个集合中相同的元素。
print(a | b) # 1 2 3 4 5 8 9 10 并集,取两个集合中所有的元素。
print(a - b) # 2 3 差集,取两个集合中不同的元素。
print(a ^ b) # 2 3 8 9 10 对称差集,取两个集合中不同的元素。
print(a <= b) # True 子集,a是b的子集。
print(a >= b) # False 超集,a不是b的超集。
print(a < b) # True 真子集,a是b的真子集。
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
当我们需要取前三个元素怎么做?
可以这么写
L[0:3]
这就是切片,这行代码的意思是从所以0处开始截取到索引3的元素
L = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
print(L[0:3])
print(L[:3]) # 从0开始,到3结束,不包含3,即0,1,2
print(L[1:3]) # 从1开始,到3结束,不包含3,即1,2
print(L[3:]) # 从3开始,到末尾,包含3,即3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
L[x:y]
切片的语法就是这样
字符串'xxx'
也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串
'ABCDEFG'[:3] # 'ABC'
'ABCDEFG'[::2] # 'ACEG'
'ABCDEFG'[::-1] # 'GFEDCBA'
我们知道 range(x) 方法可以生成从 0 到 x 的一个集合
如果要做复杂等差数列或是其他字符串的集合怎么办?
可以换一种写法: 公式 for 变量 in 集合
[x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[x * x for x in range(0,10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
可以这么理解:先执行集合循环,然后将每次迭代后的结果返回给变量,再执行一次公式。接着下一次循环
筛选
if
判断筛选结果[x * x for x in range(1, 11) if x % 2 == 0] # [4, 16, 36, 64, 100]
双层循环
a = [m + n for m in 'ABC' for n in 'XYZ']
print(a) # ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
map()
函数接收两个参数,一个是函数,一个是Iterable
,map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。
示例1:
def mapA(x):
return x * x
b = map(mapA,range(1,10))
print(b) # <map object at 0x000001C141800940>
print(list(b)) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
将数值数组转为字符串数组
c = list(map(str,range(20)))
print(c) # ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19']
reduce
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce
把结果继续和序列的下一个元素做累积计算
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
示例:
from functools import reduce
def reduceA(x,y):
return x + y
d = reduce(reduceA,range(1,10))
print(d) # 45
from functools import reduce
def reduceA(x,y):
return x + y*2
d = reduce(reduceA,range(1,10))
# 1 + 2*2 + 3*2 + 4*2 + 5*2 + 6*2 + 7*2 + 8*2 + 9*2 = 1 + 4 + 6 + 8 + 10 + 12 + 14 + 16 + 18 = 8
print(d) # 89
与map、reduce类似,filter()也接收一个函数和一个序列;
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 结果: ['A', 'B', 'C']
对具体有数字的的集合进行排序
sorted([36, 5, -12, 9, -21]) # [-21, -12, 5, 9, 36]
sorted()
函数也是一个高阶函数,它还可以接收一个key
函数来实现自定义的排序,例如按绝对值大小排序
sorted([36, 5, -12, 9, -21], key=abs) # [5, 9, -12, -21, 36]
默认情况下,对字符串排序,是按照ASCII的大小比较的,由于'Z' < 'a'
,结果,大写字母Z
会排在小写字母a
的前面。
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) # ['about', 'bob', 'Credit', 'Zoo']
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) # ['Zoo', 'Credit', 'bob', 'about']
想要进行倒叙排序,需要添加参数reverse=True
。
arr1 = [55,12,3,2,1,67,28]
print(sorted(arr1,reverse=True)) # [67, 55, 28, 12, 3, 2, 1]
arr1 = [55,12,3,2,1,67,28]
arr1.sort() # 升序
print(arr1) # [1, 2, 3, 12, 28, 55, 67]
arr1.sort(reverse=True) # 降序
print(arr1) # [67, 55, 28, 12, 3, 2, 1]
sorted(arr1) # 排序,不改变原数组,返回一个新数组,不影响原数组。
print(arr1) # [67, 55, 28, 12, 3, 2, 1]
arr1.reverse() # 反转,不改变原数组,返回一个新数组,不影响原数组。
print(arr1) # [1, 2, 3, 12, 28, 55, 67]
先看看简单的一个函数
def f(x):
return x * x
如何简化?lambda
java中
(x)=> x * x;
js
()=>{x * x}
在Python中的lambda
lambda x: x * x
我们需要使用lambda关键字,告诉Python解释器,后面的一段,属于一个匿名函数
匿名函数有个限制,就是只能有一个表达式,不用写
return
,返回值就是该表达式的结果。
结合上面的filter(),进行简化
print(list(filter(lambda x: x % 2 == 1, range(1, 20)))) # [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]