前言
这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题
于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。
微信小程序搜索:Python面试宝典
或可关注原创个人博客:https://lienze.tech
也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习
Redis
Redis
可以存储键体与五种不同数据结构类型类型之间的映射
分别为STRING
字符串、LIST
列表、SET
集合、HASH
散列和ZSET
有序集合
Redis
客户端
redis-cli
- 如需支持中文展示,可以使用参数
redis-cli --raw
字符串(STRING)
redis
中的字符串与很多语言中的字符串非常相似
字符串可以存储:字节串byte string
、整数、浮点数
- 常见指令
指令 | 解释 |
---|---|
GET | 获取存储在给定键中的值 |
SET | 设置存储在给定键中的值 |
DEL | 删除存储在给定键中的值 |
127.0.0.1:6379> set name 张三
OK
127.0.0.1:6379> get name
张三
127.0.0.1:6379> del name
1
列表(LIST)
一个列表结构可以有序的存储多个字符串
- 常见指令、
指令 | 解释 |
---|---|
LPUSH/RPUSH | 将给定的值推入列表的左/右端 |
LPOP/RPOP | 从列表的左/右端弹出一个值并返回 |
LRANGE | 获取列表在给定范围内的值 |
LINDEX | 获取列表在某个给定位置上的值 |
127.0.0.1:6379> rpush l a
1
127.0.0.1:6379> rpush l b
2
127.0.0.1:6379> rpush l c
3
127.0.0.1:6379> lrange l 0 -1
a
b
c
rpush
,是从列表的右侧推入数据,类似栈,后进入的数据在列表的头部
127.0.0.1:6379> lpush l1 a
1
127.0.0.1:6379> lpush l1 b
2
127.0.0.1:6379> lpush l1 c
3
127.0.0.1:6379> lrange l1 0 -1
c
b
a
lpush
,是从列表的左侧推入数据,类似队列,先进的在头部
127.0.0.1:6379> lpush l1 a
1
127.0.0.1:6379> lpush l1 b
2
127.0.0.1:6379> lpush l1 c
3
127.0.0.1:6379> lrange l1 0 -1
c
b
a
127.0.0.1:6379> lindex l1 2
a
集合(SET)
Redis
的集合和列表都可以存储多个字符串,但是不同在于列表可以存储多个相同的值,而集合中的数据元素是唯一的,这是由于集合通过散列表来进行维护(这些散列表只有键Key
,没有与之相关的值Value
)
此外,redis
中的结合是无序的,所以不能像列表一样的数据可以在某一端推入数据
指令 | 解释 |
---|---|
SADD | 将给定的元素添加到集合 |
SMEMBERS | 返回集合中包含的所有元素 |
SISMEMBER | 检查某元素是否包含在集合中 |
SREM | 如果元素存在与集合,那么移出该元素 |
**注意:**如果集合中包含的元素太多,那么SMEMBERS
指令的处理可能会非常慢,慎用
127.0.0.1:6379> sadd s 1
1
127.0.0.1:6379> sadd s 2
1
127.0.0.1:6379> sadd s 3
1
127.0.0.1:6379> smembers s
1
2
3
127.0.0.1:6379> sismember s 2
1
127.0.0.1:6379> sismember s a
0
127.0.0.1:6379> srem s a
0
127.0.0.1:6379> srem s 1
1
127.0.0.1:6379> smembers s
2
3
一般情况下,命令的执行如果成功,那么将会返回对应操作生效的个数,比如:1
,反之则返回0
散列(HASH)
散列可以存储多个键值对映射;散列存储的值可以是字符串、也可以是数字值
美妙的是,散列可以支持用户对其中存储的数字值进行自增或自减的操作
人们经常这样形容散列:这就像一个微缩版的Key-Value
数据库,一个微缩版的Redis
指令 | 解释 |
---|---|
HSET | 在散列里面添加给定的键值对 |
HGET | 获取指定兼职对的值 |
HGETALL | 获取散列包含的所有键值对 |
HDEL | 如果给定的键存在与散列中,那么将其删除 |
127.0.0.1:6379> hset h k1 v1
1
127.0.0.1:6379> hset h k2 v2
1
127.0.0.1:6379> hget h k1
v1
127.0.0.1:6379> hdel h k1
1
127.0.0.1:6379> hgetall h
k2
v2
hgetall
获取到的结果是竖着排列,两个为一组键值对
有序集合(ZSET)
有序集合和散列一样,都用于存储键值对
有序集合的键key
是成员,在一个有序集合中,只能有一个不同的成员
有序集合的值是value
被称为分值score
,分值为一个浮点数类型,
有序集合通过分值对键值对进行排序
基于时间衰减的商品热度值计算
指令 | 解释 |
---|---|
ZADD | 将一个带有分值的成员添加到有序集合中 |
ZRANGE | 根据元素在有序排列中所处的位置,从有序集合中获取多个元素,类似lrange |
ZRANGEBYSCORE | 获取有序集合中在给定分值范围内的成员 |
ZREM | 如果给定成员存在与有序集合中,那么移出这个成员 |
127.0.0.1:6379> ZADD z 5 first
(integer) 1
127.0.0.1:6379> ZADD z 3 second
(integer) 1
127.0.0.1:6379> ZRANGE z 0 -1
1) "second"
2) "first"
127.0.0.1:6379> ZRANGE z 0 -1 withscores
1) "second"
2) "3"
3) "first"
4) "5"
127.0.0.1:6379> ZADD z 4.5 third
(integer) 1
127.0.0.1:6379> ZRANGE z 0 -1 withscores
1) "second"
2) "3"
3) "third"
4) "4.5"
5) "first"
6) "5"
127.0.0.1:6379> zrem z third
(integer) 1
127.0.0.1:6379> ZRANGE z 0 -1
1) "second"
2) "first"
字符串其他操作
自增、自减
当一个值被存入Redis
时,如果这个值可以被解释成十进制或者浮点数,那么Redis
会检测到这一属性
并允许用户可以对这样的值进行自增和自减操作
指令 | 解释 |
---|---|
INCR | 将键存储的值增长1 |
DECR | 将键存储的值减去1 |
INCRBY | 将键存储的值加上整数 |
DECRBY | 将键存储的值减去整数 |
INCRBYFLOAT | 将键存储的值加上浮点数(传递负值即为减去)、在redis2.6及以上版本可用 |
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> incr age
(integer) 2
127.0.0.1:6379> get age
"2"
127.0.0.1:6379> decr age
(integer) 1
127.0.0.1:6379> get age
"1"
在Python
的代码中,只需要使用incr
即可包含incrby
的功能
127.0.0.1:6379> incrby age 10
(integer) 11
127.0.0.1:6379> get age
"11"
127.0.0.1:6379> decrby age 5
(integer) 6
127.0.0.1:6379> get age
"6"
127.0.0.1:6379> incrbyfloat age -2.5
"3.5"
子串
像python
的切片操作一样,Redis
中的字符串也支持对某个范围进行操作
指令 | 解释 |
---|---|
APPEND | 将一个值追加到给定字符串的末尾 |
GETRANGE | 给定起点、终点,获取该范围内所有的字符组成的子串,包括起点重点,左闭右闭 |
SETRANGE | 将字符串从某个偏移量开始设置成给定的值 |
127.0.0.1:6379> set name abc
OK
127.0.0.1:6379> append name aaa
(integer) 6
127.0.0.1:6379> get name
"abcaaa"
现在版本的getrange
是由老版本的substr
函数改名而来,如果使用2.6版本以上的redis
,建议使用getrange
127.0.0.1:6379> getrange name 2 4
"caa"
127.0.0.1:6379> substr name 2 4
"caa"
# 左闭右闭
127.0.0.1:6379> getrange name 0 -1
"abcaaa"
127.0.0.1:6379> setrange name 2 ***
(integer) 6
127.0.0.1:6379> get name
"ab***a"
列表其他操作
范围裁剪
除了以上对于列表某个位置或范围的访问,以及对列表左或右侧推入、弹出数据的命令
还可以通过LTRIM
对列表进行裁剪
指令 | 解释 |
---|---|
LTRIM | 给定起点和终点,对列表进行裁剪,只保留该范围内的数据 |
# l: 4, 3, 2, 1
127.0.0.1:6379> ltrim l 1 3
OK
127.0.0.1:6379> lrange l 0 -1
1) "2"
2) "1"
元素移动
redis
还支持在两个列表之间进行数据移动,从某个列表中pop
数据,然后push
到另外一个列表中
指令 | 解释 |
---|---|
RPOPLPUSH source dest | 从source列表中弹出最右端的数据,并从最左端推入dest列表中 |
BRPOPLPUSH source dest timeout | timeout参数代表当source列表为空时,该命令阻塞等待可弹出数据,超过时间则返回None |
# l1: 2,1
# l2: a,
127.0.0.1:6379> lrange l1 0 -1
1) "2"
127.0.0.1:6379> lrange l2 0 -1
1) "1"
2) "a"
阻塞弹出
指令 | 解释 |
---|---|
BLPOP | 阻塞等待timeout时间,从一个非空列表中弹出最左侧的元素,超时返回None |
BRPOP | 与上同,只是从列表的最右侧弹出元素 |
这俩命令本质上与普通的LPOP
和RPOP
差不多,只是多了阻塞行为
集合其他操作
计数、随机
唯一、无序
指令 | 解释 |
---|---|
SCARD | 返回集合中包含元素的数量 |
SRANDMEMBER KEY COUNT | 从key的集合中随机返回COUNT个数量的元素 |
SPOP KEY COUNT | 随机移除COUNT个元素,并返回被移除的元素 |
127.0.0.1:6379> smembers s1
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> scard s1
(integer) 3
127.0.0.1:6379> srandmember s1 2
1) "2"
2) "1"
127.0.0.1:6379> srandmember s1 2
1) "2"
2) "3"
127.0.0.1:6379> spop s1 2
1) "2"
2) "3"
127.0.0.1:6379> smembers s1
1) "1"
组合
指令 | 解释 |
---|---|
SMOVE SOURCE DEST ITEM | 如果ITEM存在与SOURCE中,那么将其移除并添加到DEST集合中,成功返回1,反之返回0 |
127.0.0.1:6379> sadd s1 a
(integer) 1
127.0.0.1:6379> sadd s2 *
(integer) 1
127.0.0.1:6379> smove s1 s2 a
(integer) 1
127.0.0.1:6379> smove s1 s2 a
(integer) 0
127.0.0.1:6379> smembers s2
1) "*"
2) "a"
127.0.0.1:6379> smembers s1
(empty list or set)
差集、交集、并集
与数学中的语义一致
指令 | 解释 |
---|---|
SDIFF KEY1 KEY2… | 返回存在与KEY1而不存在于其他集合中的元素(差集) |
SDIFFSTORE DEST KEY1 KEY2… | 返回存在与KEY1而不存在于其他集合中的元素(差集),并存储到DEST 中 |
SINTER KEY1 KEY2… | 返回同时存在于所有集合中的元素(交集) |
SINTERSTORE DEST KEY1 KEY2… | 返回同时存在于所有集合中的元素(交集),并存储到DEST 中 |
SUNION KEY1 KEY2… | 返回那些至少存在于一个集合中的元素(并集) |
SUNIONSTORE DEST KEY1 KEY2 | 返回那些至少存在于一个集合中的元素(并集),并存储到DEST 中 |
127.0.0.1:6379> sdiffstore dest s2 s1
(integer) 2
127.0.0.1:6379> smembers dest
1) "*"
2) "a"
# dest: *, a
# s2: *, a
# s3: ~
127.0.0.1:6379> sunion dest s2
1) "*"
2) "a"
127.0.0.1:6379> sunion dest s2 s3
1) "*"
2) "~"
3) "a"
散列其他操作
批量存储
之前的是单独的key
、value
存储
来看看更高级的批量键值获取存储,这样的操作可以减少命令的调用次数,以及客户端与Redis
之间的通信往返次数来提升Redis
的性能
指令 | 解释 |
---|---|
HMGET | 从一个散列获取一个或多个值 |
HMSET | 为散列设置一个或多个值 |
HLEN | 返回散列包含的键值对数量 |
127.0.0.1:6379> hmset hm a 1 b 2 c 3
OK
127.0.0.1:6379> hmget hm a b c
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> hlen hm
(integer) 3
获取、检查
Redis
的散列还可以像Python
中的字典一样,支持集成了很多功能
指令 | 解释 |
---|---|
HEXISTS | 检查给定的键是否在散列中 |
HKEYS | 获取散列包含的所有键 |
HVALS | 获取散列包含的所有值 |
HINCRYBY | 将键存储的值加上一个整数 |
HINCRYBYFLOAT | 将键存储的值加上一个浮点数 |
127.0.0.1:6379> hset h a 1
(integer) 1
127.0.0.1:6379> hexists h a
(integer) 1
127.0.0.1:6379> hexists h b
(integer) 0
# h: { 1:a, 2:b }
127.0.0.1:6379> hvals h
1) "v2"
2) "1"
3) "2"
127.0.0.1:6379> hkeys h
1) "k2"
2) "a"
3) "b"
使用getall
在大量数据的情况下,可以先使用hkeys
,然后再使用hget
一个个的取出键的值
有序集合其他操作
计数、区间
有序集合主要是通过分值大小有序的进行获取和扫描成员
指令 | 解释 |
---|---|
ZCARD | 返回有序集合的数据成员数量 |
ZINCRBY | 将有序集合某个成员的分值加上某个值 |
ZCOUNT KEY MIN MAX | 返回分值介于min和max之间的成员数量 |
ZRANK KEY MEMBER | 返回成员在有序集合中的排名 |
ZSCORE | 返回成员的分值 |
127.0.0.1:6379> zcard z
(integer) 2
# a2:5 a3:7 a1:10
127.0.0.1:6379> zadd z 10 a1
(integer) 1
127.0.0.1:6379> zadd z 5 a2
(integer) 1
127.0.0.1:6379> zadd z 7 a3
(integer) 1
127.0.0.1:6379> zrange z 0 -1
1) "a2"
2) "a3"
3) "a1"
127.0.0.1:6379> zcount z 7 10
(integer) 2
127.0.0.1:6379> zrank z a2
(integer) 0
127.0.0.1:6379> zrank z a3
(integer) 1
127.0.0.1:6379> zrank z a1
(integer) 2
127.0.0.1:6379> zscore z a1
"10"
范围删除、获取
除了正向的排序,还可以通过分值逆向排序提取结果
还可以对有序集合进行范围移除
指令 | 解释 |
---|---|
ZREVRANK | 返回从大到小的单个元素的排名 |
ZREVRANGE | 返回有序集合给定排名范围内的成员,成员按照分值从大到校排列 |
ZRANGEBYSCORE KEY MIN MAX | 返回介于某个分值之间的所有元素 |
ZREVRANGEBYSCORE | 返回介于某个分值之间的所有元素并逆序 |
ZREMRANGEBYRANK KEY START STOP | 移除介于某个排名区间之间的所有元素 |
ZREMRANGEBYSCORE KEY MIN MAX | 移除介于某个分值之间的所有元素 |
ZINTERSTORE | 执行交集运算 |
ZUNIONSTORE | 执行并集运算 |
127.0.0.1:6379> zrange z 0 -1
1) "a2"
2) "a3"
3) "a1"
127.0.0.1:6379> zrevrank z a3
(integer) 1
127.0.0.1:6379> zrevrank z a2
(integer) 2
127.0.0.1:6379> zrevrank z a1
(integer) 0
127.0.0.1:6379> zrevrange z1 0 -1
1) "zhangsan"
2) "wangwu"
3) "lisi"
127.0.0.1:6379> zrange z1 0 -1
1) "lisi"
2) "wangwu"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore z1 99.5 100
1) "wangwu"
2) "zhangsan"
127.0.0.1:6379> zremrangebyrank z1 0 1
(integer) 2
127.0.0.1:6379> zrange z1 0 1
1) "zhangsan"