先总结学到的内容:
一.字典比比列表快
二.优化概率排序
三.整体流程:1.不存在就创建一个字典记录下密码,次数为1。
2.若存在了,就次数+1
3.sorted一般返回的是一个list,然而处理风格是[[“123456”,7]]
4.看17、18行的解释了解到sorted
5.24行有一个内存优化,如何优化的呢,把生成的字典删除因为已经有了所需要的mylist,我眼里mylist就是排了序的csdnpassworddict,因此csdnpassword没了用处
filepath=r"xxx" csdnfile = open(filepath, "rb")#rb以二进制方式读取文件,改文件必须已经存在 csdnpassworddict={} while True: line=csdnfile.readline() if not line: #最后一句跳出 break line=line.decode("gbk",errors="ignore") linelist=line.split(" # ") password = linelist[1]#密码 if password not in csdnpassworddict: csdnpassworddict[password]=1 else: csdnpassworddict[password]=csdnpassworddict[password]+1 csdnfile.close() print("密码字典生成次数") #根据key,根据次数排序,排序所有的元素,按照次数,从大到小 #item取出字典里所有的元素,每个字典里既有key又有value;x:x[1]是根据进行次数排序 mylist = sorted(csdnpassworddict.items(),key=lambda x:x[0],reverse=True) print(type(mylist),"类型") #[["123456",7]] print("密码字典排序完成") del csdnpassworddict #节约内存 print("内存优化") savefilepath=r"xxxx" savefile = open(savefilepath,"wb")#以二进制方式写入文件 for key in mylist: savefile.write((str(key[1])+"#"+key[0]+"\r\n").encode("utf-8"))#\r\n回车换行 savefile.close()
redis | 含义 |
---|---|
String | 字符串 |
Hash | 哈希 |
list | 列表 |
Set | 集合 |
Sorted | 有序集合 |
string是 redis最基本的类型,一个 key对应一个 value。 string 类型是二进制安全的。意思是 redis 的 string可以包含任何数据。比如 jpg图片或者序列化的对象 string 类型是 Redis最基本的数据类型,一个键最大能存512MB。
小技巧:set与get是一对,存于取
redis 127.0.0.1:6379> SET name "yincheng" OK redis 127.0.0.1:6379> GET name "yincheng" 127.0.0.1:6379> type name string
删除键值
redis 127.0.0.1:6379> del name
验证键是否存在
redis 127.0.0.1:6379> exists name (integer) 0
在上面的例子中,SET 和 GET 是 Redis STRING 命令, name 和 yincheng 是存储在 Redis 的键和字符串
值。
Redis hash 是一个键值对集合,必须成对出现。
Redis hash是一个 string类型的 field 和 value 的映射表,hash特别适合用于存储对象。
127.0.0.1:6379> HMSET my_hash_table username yincheng age 18 sex male OK 127.0.0.1:6379> HGETALL my_hash_table 1) "username" 2) "yincheng" 3) "age" 4) "18" 5) "sex" 6) "male"
在上面的例子中,哈希数据类型用于存储包含用户基本信息的用户对象。
这里 HSET,HGETALL 是 Redis HASHES 命令, 同时 my_hash_table 也是一个键。
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部
(右边)。
小技巧:lpush=list push lrange=list range lrange需要包括1-3里的一个不然报错误:empty
redis 127.0.0.1:6379> lpush tutorial_list redis (integer) 1 redis 127.0.0.1:6379> lpush tutorial_list mongodb (integer) 2 redis 127.0.0.1:6379> lpush tutorial_list rabbitmq (integer) 3 redis 127.0.0.1:6379> lrange tutorial_list 0 10 1) "rabitmq" 2) "mongodb" 3) "redis"
列表最多可存储 2 32 - 1 元素 (4294967295, 每个列表可存储 40 多亿)。
Redis Set 是 string 类型的无序集合。 集合是通过哈希表实现的,所以
添加,删除,查找的复杂度都是 O(1)。 在 Redis 可以添加,删除和测试
成员存在的时间复杂度为 O(1)。
小技巧:sadd=set add smembers=set members
Redis 基本数据类型 12 127.0.0.1:6379> sadd myset redis (integer) 1 127.0.0.1:6379> sadd myset mongodb (integer) 1 127.0.0.1:6379> sadd myset rabitmq (integer) 1 127.0.0.1:6379> sadd myset rabitmq (integer) 0 127.0.0.1:6379> smembers myset 1) "mongodb" 2) "redis" 3) "rabitmq"
注:在上面的例子中 rabitmq 被添加两次,但由于它是只集合具有唯一特性。 集合中最大的成员数
为 2 32 - 1(4294967295, 每个集合可存储 40多亿个成员)。
Redis zset 和 set 一样也是 string 类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个
double 类型的分数(权重)。redis 正是通过分数来为集合中的成员(权重)进行
从小到大的排序。
zset 的成员是唯一的,但分数(score)却可以重复
127.0.0.1:6379> zadd mysortset 0 redis (integer) 1 127.0.0.1:6379> zadd mysortset 2 mongodb (integer) 1 127.0.0.1:6379> zadd mysortset 1 rabitmq (integer) 1 127.0.0.1:6379> ZRANGEBYSCORE mysortset 0 1000 1) "redis" 2) "rabitmq" 3) "mongodb"
直接调用redis库
import redis #连接数据库 try: myredis=redis.StrictRedis(host="127.0.0.1", port=6379, db=0, password="") myredis.set("hello", "密码正确") print(myredis.get("hello").decode("utf-8")) myredis.delete("hello") print(myredis.get("hello").decode("utf-8")) except: print("密码错误")
学到的心得:当出现错误时候,看一下类型,比如这个mydict[b"sunyu"]因为是二进制所以要加一个b。
import redis myredis = redis.StrictRedis(host="127.0.0.1", port=6379, db=0, password="") myredis.hset("user:password","yincheng","111111") myredis.hset("user:password","sunyu","111111abc") print(myredis.hgetall("user:password")) mydict=myredis.hgetall("user:password") print(type(mydict)) print(mydict) print(mydict[b"sunyu"])#这个属于二进制所以要加b print(myredis.hkeys("user:password"))#这个代表key
并不困难理解起来,链接redis之后,一个类型的次数用incr()来增加
import redis myredis = redis.StrictRedis(host="127.0.0.1", port=6379, db=0, password="") myredis.set("qazwsx",2000) myredis.incr("qazwsx")#相当于次数加一 myredis.incr("qazwsx") print(myredis.get("qazwsx")) print(myredis.get("qazwsxedc"))#None表示不存在,存在返回值
对于通道的理解:线程可能会有多个,那么就把所有线程都开始加入通道运行,之后直接读取所有的结果,如果里面有一个错误,那么就报错。
import redis myredis = redis.StrictRedis(host="127.0.0.1", port=6379, db=0, password="") myp=myredis.pipeline()#构建一个管道 提问:什么是管道? myp.set("gaoqinghua","baby") myp.sadd("hechengcheng","go")#set add 简称sadd myp.execute()#执行 print(myredis.get('gaoqinghua'))
自己的理解:给一个频道发消息,底下所有的订阅者都能收到,看一下给的解释吧。
在 Redis 中,你可以设定对某一个 key 值进行消息发布及消息订阅,当一个 key 值上进行了消息发布后,所
有 订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即
时聊 天,群聊等功能。
这个案例视频没给出,但在文档中用了,比较好理解:
微信班级群 class:20170101,发布订阅模型
学生A B C
订阅一个主题名叫:class20170101
127.0.0.1:6379> SUBSCRIBE class:20170101 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "redisChat" 3) (integer) 1
学生A:
针对 class:20170101 主题发送 消息,那么所有订阅该主题的用户都能够收到该数据。
127.0.0.1:6379> PUBLISH class:20170101 "i love peace!" (integer) 1
学生B:
针对 class:20170101 主题发送 消息,那么所有订阅该主题的用户都能够收到该数据。
127.0.0.1:6379> PUBLISH class:20170101 "go to hell" (integer) 1
最后学生C会收到A和B发送过来的消息:
python@ubuntu:~$ redis-cli 127.0.0.1:6379> SUBSCRIBE class:20170101 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "class:20170101" 3) (integer) 1 1) "message" 2) "class:20170101" 3) "i love peace!" 1) "message" 2) "class:20170101" 3) "i love peace!" 1) "message" 2) "class:20170101" 3) "go to hell"