Python 的dict是一种数据结构,json 是一种数据传输格式。json 就是一个根据某种约定格式编写的纯字符串,不具备任何数据结构的特征。而 python 的dict的字符串表现形式的规则看上去和 json 类似,但是dict本身是一个完整的数据结构,实现了一切自身该有的算法。
Python的dict的key可以是任意可hash对象,json只能是字符串。形式上有些相像,但json是纯文本的,无法直接操作。
json的格式要求必须且只能使用双引号作为key或者值的边界符号,不能使用单引号,而且"key"必须使用边界符(双引号),但dict就无所谓了。
python的dict的Key是唯一的,而json的Key可以重复。
python 的dict可以嵌套tuple, json里只有array。
json在python中的数据处理:
1. 序列化: dic对象 ➡ json字符串(存储,传输) 编码
2. 反序列化:json ➡dic (分析,处理)解码
import json json.loads() # 将json数据转化成dict数据 json.dumps() # 将dict数据转化成json数据 json.load() # 读取json文件数据,转成dict数据 json.dump() # 将dict数据转化成json数据后写入json文件
读取json文件,并转为dict
with open('.../XXX.json','r') as f: data= json.load(f) 或者: data = json.load(open('.../XXX.json','r'))
将dict数据转化为json,并写入json文件
with open('json_data.txt','w+') as f: json.dump(dict_data,f)
取键、值、键值对
# 字典在for迭代中默认只输出key for k in dict_data: print(k) # 迭代输出key for k in dict_data.keys(): print(k) # 迭代输出value for v in dict_data.values(): print(v) # 迭代输出键值对 for k,v in dict_data.items(): print(k,v)
dict的增删改:
# 增加一个键值对: dd['new_key'] = 'XXX' # 改键值 dd['key'] = 'XX' # 删除键值对 del['key'] # 删除字典第一层的键值对 del['key1']['key2']['key3'] # 删除多层嵌套里的键值对 dd.pop('key') # 删除键值对,并返回对应的value # 判断是否为字典格式 isinstance(data,dict)
获取多层嵌套dict的键值对:
def get_all_dict(data): if isinstance(data,dict): for x in range(len(data)): temp_key = list(data.keys())[x] temp_value = data[temp_key] print('KEY --> {}\nVALUE --> {}'.format(temp_key,temp_value)) print('\t') get_all_dict(temp_value) # 迭代输出结果
dict1 = {'a':1,'b':2,'c':3,'d':4} dict2 = {'a':1,'b':2,'c':5,'e':6} differ = set(dict1.items()) ^ set(dict2.items()) print(differ) #所有差异 #输出:{('c', 3), ('e', 6), ('c', 5), ('d', 4)} diff = dict1.keys() & dict2 diff_vals = [(k, dict1[k], dict2[k]) for k in diff if dict1[k] != dict2[k]] print(diff_vals) #相同key,不同value #输出:[('c', 3, 5)]
其他参考
a = { "x":1, "y":2, "z":3 } b = { "x":1, "w":11, "z":12 } print(a.items()) >>>dict_items([('x', 1), ('y', 2), ('z', 3)]) # 查看两个字典共有的key print(a.keys() & b.keys()) >>>{'x', 'z'} # 查看字典a 和字典b 的不共有的key print(a.keys() ^ b.keys()) >>>{'y'} # 查看在字典a里面而不在字典b里面的key print(a.keys() - b.keys()) >>>{('x', 1)} # 查看字典a和字典b相同的键值对 print(a.items() & b.items()) >>>{'w', 'y'}
import json d = {"name":None} s = json.dumps(d) s = s.replace('null', '\"null\"') d = json.loads(s) print(d) >> {'name':'null'}
其他说明:
在pandas中, 如果其他的数据都是数值类型, pandas会把None自动替换成NaN, 甚至能将s[s.isnull()]= None,和s.replace(NaN, None)操作的效果无效化。 这时需要用where函数才能进行替换。
None能够直接被导入数据库作为空值处理, 包含NaN的数据导入时会报错。
numpy和pandas的很多函数能处理NaN,但是如果遇到None就会报错。
None和NaN都不能被pandas的groupby函数处理,包含None或者NaN的组都会被忽略。
总之,None是python自带的,而NaN则是被numpy和pandas所支持的
等值性比较的总结:(True表示被判定为相等)
trip[0]:
{'pickup_latitude': '40.64499', 'pickup_longitude': '-73.78115', 'trip_distance': '18.38'}
处理方式:
for list_dict in list_of_dicts: for key, value in list_dict.items(): list_dict[key] = float(value)
nid = "1,2" print(nid.split(',')) datas = [] for i in nid.split(','): mydict = {} mydict["id"] = str(i) mydict["checked"] = True datas.append(mydict) print(str(datas))
输出:
['1', '2'] [{'id': '1', 'checked': True}, {'id': '2', 'checked': True}]
--空 select id , num = (case when col1 is null then 1 else 0 end) + (case when col2 is null then 1 else 0 end) + (case when col3 is null then 1 else 0 end) + (case when col4 is null then 1 else 0 end) from tb --非空 select id , num = (case when col1 is not null then 1 else 0 end) + (case when col2 is not null then 1 else 0 end) + (case when col3 is not null then 1 else 0 end) + (case when col4 is not null then 1 else 0 end) from tb
项目中生成最多非空列的table
select id , case when filed !='' then 1 else 0 end as num from ods_crd_ddt_external_dev.vira_ft_ods_issue_s3_di_pt vfoisdp order by num desc limit 10
>>> keys = ['a', 'b', 'c'] >>> values = [1, 2, 3] >>> dictionary = dict(zip(keys, values)) >>> print(dictionary) {'a': 1, 'b': 2, 'c': 3}
没有zip的写法
l1 = [1,2,3,4,5] l2 = ['a','b','c','d','e'] d1 = {} for l1_ in l1: for l2_ in l2: d1[l1_] = l2_ l2.remove(l2_) break print (d1) {1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}
students = { '小甲':18, '小乙':20, '小丙':15 } 1、只取字典的键,组成新的列表 b = [ key for key,value in students.items() ] b = [ '小甲', '小乙','小丙' ] 2、字典的键值对互换,组成新的字典; b = { value:key for key,value in students.items() } b = { 18:'小甲', 20:'小乙', 15:'小丙' }
[{'LT/C_score': 0.44917283324979085, 'class_uncertainty': 0.060122907161712646, 'image_id': 286849}, {'LT/C_score': 0.8943103022795436, 'class_uncertainty': 0.009622752666473389, 'image_id': 540932}, {'LT/C_score': 0.8732056996282929, 'class_uncertainty': 0.00022846460342407227, 'image_id': 32901}, {'LT/C_score': 0.8979904106858694, 'class_uncertainty': 0.002511739730834961, 'image_id': 324614}, {'LT/C_score': 0.8679021984870174, 'class_uncertainty': 0.0019818544387817383, 'image_id': 270474}, {'LT/C_score': 0.7331004226857969, 'class_uncertainty': 0.00713348388671875, 'image_id': 139}, {'LT/C_score': 0.11941635694217467, 'class_uncertainty': 0.0169374942779541, 'image_id': 241677}, {'LT/C_score': 0.02415653156423425, 'class_uncertainty': 0.014993846416473389, 'image_id': 528399}, {'LT/C_score': 0.1769359589898254, 'class_uncertainty': 0.2365768551826477, 'image_id': 565391}, {'LT/C_score': 0.866919080778817, 'class_uncertainty': 0.0014355778694152832, 'image_id': 196754}]
import json import os def write_list_to_json(list, json_file_name, json_file_save_path): """ 将list写入到json文件 :param list: :param json_file_name: 写入的json文件名字 :param json_file_save_path: json文件存储路径 :return: """ os.chdir(json_file_save_path) with open(json_file_name, 'w') as f: json.dump(list, f)
txt文本文件能存储各式各样数据,结构化的二维表、半结构化的json,非结构化的纯文本。
存储在excel、csv文件中的二维表,都是可以直接存储在txt文件中的。
半结构化的json也可以存储在txt文本文件中。
最常见的是txt文件中存储一群非结构化的数据:
从txt中读出json类型的半结构化数据
import pandas as pd import json f = open("../data/test.txt","r",encoding="utf-8") data = json.load(f)
需要注意的是json必须是双引号:"" 才能操作
通过以下命令获取数据类型
type(data) # print(type(data))
有如下格式json文件
{"ID": "001", "name": "a", age: "12"} {"ID": "002", "name": "b", age: "23"} {"ID": "003", "name": "c", age: "42"} ...
将json文件按行转为字典数据并存入list
#!/usr/bin/python3 # coding=utf-8 import json papers = [] # 该数组每行都是字典数据{} file = open("E:\\pycharm1\\testset2.json", 'r', encoding = 'utf-8') # 上面路径是我的json文件所在地,后面包含中文编码 for line in file.readlines(): dic = json.loads(line) papers.append(dic)
以key "name"为例,对提取出的数据按照属性进行分析:
for line in range(0, len(papers)): S1 = (papers[line])['name'] # 读取key为name的value
list1 = ['1','2','3','4'] fileObject = open('list.txt','w') for word in list1: fileObject.write(word) fileObject.write('\n') fileObject.close()
这里用open函数读取了一个txt文件,”encoding”表明了读取格式是“utf-8”,还可以忽略错误编码。
另外,使用with语句操作文件IO是个好习惯,省去了每次打开都要close()
with open("list.txt","r",encoding="utf-8",errors='ignore') as f: data = f.readlines() for line in data: word = line.strip() #list print(word)
读取数据为numpy的数组,可以进一步转换为list对象
array_ = numpy.loadtxt('list.txt') list_ = list(array_)
例子1
这样去操作txt文件里的json数据会导致存入的都是str
方法一:
import sys result=[] with open('accounts.txt','r') as f: for line in f: result.append(list(line.strip('\n').split(','))) print(result)
输出:
方法二:
处理数据:
第一步:读取文件中的数据
读取文件中的数据比较简单,代码运行如下:
读取文件后的数据,发现是这是些详细的字符串,可以通过打印来看下效果:
打印的结果比较像txt文本中的内容,但是在python中是作为一系列字符串存储的,用字符串的split函数把每个数字切割成单独的字符串
第二步:数据的转换
以上可以精简为三行代码:
file = open ('....txt','r') S = file.read().split() P = list(int(i) for i in S)
例子2
方法一:
f=open('唐诗一百首.txt', encoding='gbk') txt=[] for line in f: txt.append(line.strip()) print(txt)
line.strip() 去除首尾空格
encoding 编码格式 utf-8,gbk
方法二:
f=open('唐诗一百首.txt') line = f.readline().strip() #读取第一行 txt=[] txt.append(line) while line: # 直到读取完文件 line = f.readline().strip() # 读取一行文件,包括换行符 txt.append(line) f.close() # 关闭文件 print(txt)
import json dictObj = { 'andy':{ 'age': 23, 'city': 'shanghai', 'skill': 'python' }, 'william': { 'age': 33, 'city': 'hangzhou', 'skill': 'js' } } jsObj = json.dumps(dictObj) fileObject = open('jsonFile.json', 'w') fileObject.write(jsObj) fileObject.close()
with open('data.json', 'r') as f: data = json.load(f)
with open('data.json', 'w') as f: json.dump(data, f)
file_path = 'C:/...' fi=open(file_path,'r') txt=fi.readlines() a=[] for w in txt: w=w.replace('\n','') a.append(w) print(a)
c=[10,20,20,20,20,100,30,50,50,50] d=[20,20,30,40,50] for i in range(len(c)): for j in c: if j in d: c.remove(j) d.remove(j) print(c) print(d) #[10, 20, 20, 100, 50, 50] #[40]
#!/usr/bin/python # -*- coding: UTF-8 -*- dict = {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.csdn.net'} dict.clear(); # 清空词典所有条目
#!/usr/bin/python # -*- coding: UTF-8 -*- site= {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.csdn.net'} pop_obj=site.pop('name') # 删除要删除的键值对,如{'name':'我的博客地址'}这个键值对 print pop_obj # 输出 :我的博客地址
#!/usr/bin/python # -*- coding: UTF-8 -*- site= {'name': '我的博客地址', 'number': 10000, 'url':'http://blog.csdn.net'} pop_obj=site.popitem() # 随机返回并删除一个键值对 print pop_obj # 输出结果可能是{'url','http://blog.csdn.net/uuihoo'}
#!/usr/bin/python # -*- coding: UTF-8 -*- site= {'name': '我的博客地址', 'alexa': 10000, 'url':'http://blog.csdn.net/uuihoo/'} del site['name'] # 删除键是'name'的条目 del site # 清空字典所有条目
给定一个字典, 移除字典点键值(key/value)对。
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4} # 输出原始的字典 print ("字典移除前 : " + str(test_dict)) # 使用 del 移除 Zhihu del test_dict['Zhihu'] # 输出移除后的字典 print ("字典移除后 : " + str(test_dict)) # 移除没有的 key 会报错 #del test_dict['Baidu']
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4} 字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4} # 输出原始的字典 print ("字典移除前 : " + str(test_dict)) # 使用 pop 移除 Zhihu removed_value = test_dict.pop('Zhihu') # 输出移除后的字典 print ("字典移除后 : " + str(test_dict)) print ("移除的 key 对应的 value 为 : " + str(removed_value)) print ('\r') # 使用 pop() 移除没有的 key 不会发生异常,我们可以自定义提示信息 removed_value = test_dict.pop('Baidu', '没有该键(key)') # 输出移除后的字典 print ("字典移除后 : " + str(test_dict)) print ("移除的值为 : " + str(removed_value))
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4} 字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3} 移除的 key 对应的 value 为 : 4 字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3} 移除的值为 : 没有该键(key)
test_dict = {"Runoob" : 1, "Google" : 2, "Taobao" : 3, "Zhihu" : 4} # 输出原始的字典 print ("字典移除前 : " + str(test_dict)) # 使用 pop 移除 Zhihu new_dict = {key:val for key, val in test_dict.items() if key != 'Zhihu'} # 输出移除后的字典 print ("字典移除后 : " + str(new_dict))
执行以上代码输出结果为:
字典移除前 : {'Runoob': 1, 'Google': 2, 'Taobao': 3, 'Zhihu': 4} 字典移除后 : {'Runoob': 1, 'Google': 2, 'Taobao': 3}
删除字典中的键值对的有del语句与pop方法,del 语句和 pop() 函数作用相同,pop() 函数有返回值,返回值为对应的值,del语句没有返回值。pop()函数语法:pop(key[,default]),其中key: 要删除的键值,default: 如果没有 key,返回 default 值
dic = {"张三": 24, "李四": 23, "王五" : 25, "赵六" : 27} del dic["张三"] print(dic) print(dic.pop("李四")) print(dic)
输出:
{"李四": 23, "王五" : 25, "赵六" : 27} 23 {"王五" : 25, "赵六" : 27}
2019-02-22更新:
从python3.7开始,字典按照插入顺序,实现了有序。修改一个已存在的key的值,不影响顺序,如果删了一个key后再添加该key,该key会被添加至末尾。标准json库的dump(s)/load(s)也是有序的
https://docs.python.org/3/library/stdtypes.html#dict.values
list_before = [1, 2, 3, 4, 5] list_after = [val for val in list_before for i in range(2)]
输出:
list_after = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
def data_flatten(key,val,con_s='_',basic_types=(str,int,float,bool,complex,bytes)): """ 数据展开生成器,以键值对为最基础的数据 param key: 键,默认为基础类型数据,不做进一步分析 param val: 值,判断值的数据类型,如果为复杂类型就做进一步分析 param con_s: 拼接符,当前级的键与父级键拼接的连接符,默认为_ param basic_types: 基础数据类型元组,如果值的类型在元组之内,则可以输出 return: 键值对元组 """ if isinstance(val, dict): for ck,cv in val.items(): yield from data_flatten(con_s.join([key,ck]).lstrip('_'), cv) elif isinstance(val, (list,tuple,set)): for item in val: yield from data_flatten(key,item) elif isinstance(val, basic_types) or val is None: yield str(key).lower(),val
样例数据:
test_dict = { 'a':1, 'b':2, 'c':[1,2,3,4,{'a':1,'b':2,'c':3}], 'd':{ 'a':2, 'b':3, 'c':('1','2','3'), 'd':{ 'a':1, 'b':['True','False'] } }, 'e':{123,3,34,'les'} }
调用:
for i in data_flatten('',test_dict): print(i)
输出:
def prefix_dict(di_, prefix_s=''): """ 把字典的每个key都带上前缀prefix_s :param di_: :param prefix_s: :return: """ return {prefix_s + k: v for k, v in di_.items()} def spear_dict(di_, con_s='.'): """ 展开dict(如果下层还是dict),需要递归,展开到下层的数据类型不是字典为止 可能实用的地方:将文档类的数据格式化成更加关系化的样子可能有用 :param di_: 输入字典 :param con_s: 层级间的连接符号 :return: 深度不大于1的字典,嵌套的其他数据类型照旧 """ ret_di = {} for k, v in di_.items(): if type(v) is dict: v = spear_dict(v) # 这里或许有不写到这一层的更好写法 # for k_, v_ in v.items(): # ret_di.update({con_s.join([k, k_]): v_}) ret_di.update(prefix_dict(v, prefix_s=k + con_s)) else: ret_di.update({k: v}) return ret_di
>>> di_ {'title': '新田商业街', 'reliability': 7, 'addressComponents': {'streetNumber': '', 'city': '深圳市', 'street': '', 'province': '广东省', 'district': '龙华区'}, 'location': {'lng': 114.09127044677734, 'lat': 22.700519561767578}, 'adInfo': {'adcode': '440309'}, 'level': 11, 'more_deep': {'loca': {'lng': 114.09127044677734, 'lat': 22.700519561767578}}} >>> spear_dict(di_) {'title': '新田商业街', 'reliability': 7, 'addressComponents.streetNumber': '', 'addressComponents.city': '深圳市', 'addressComponents.street': '', 'addressComponents.province': '广东省', 'addressComponents.district': '龙华区', 'location.lng': 114.09127044677734, 'location.lat': 22.700519561767578, 'adInfo.adcode': '440309', 'level': 11, 'more_deep.loca.lng': 114.09127044677734, 'more_deep.loca.lat': 22.700519561767578} spear_dict(di_, '_') {'title': '新田商业街', 'reliability': 7, 'addressComponents_streetNumber': '', 'addressComponents_city': '深圳市', 'addressComponents_street': '', 'addressComponents_province': '广东省', 'addressComponents_district': '龙华区', 'location_lng': 114.09127044677734, 'location_lat': 22.700519561767578, 'adInfo_adcode': '440309', 'level': 11, 'more_deep_loca.lng': 114.09127044677734, 'more_deep_loca.lat': 22.700519561767578}
问题1:对于列表形如 list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]] 转化成列表 list_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9] 的问题。
# 普通方法 list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]] list_2 = [] for _ in list_1: list_2 += _ print(list_2) # 列表推导 list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]] list_2 = [i for k in list_1 for i in k] print(list_2) # 使用sum list_1 = [[1, 2], [3, 4, 5], [6, 7], [8], [9]] list_2 = sum(list_1, []) print(list_2)
问题2:对于复杂一些的,如:list =[1,[2],[[3]],[[4,[5],6]],7,8,[9]],上面的方法就不好使了。得换个方法了,这里使用递归的方法解决。
def flat(nums): res = [] for i in nums: if isinstance(i, list): res.extend(flat(i)) else: res.append(i) return res
实习期间学到了两种验证方式:
Token验证与用户名加密码验证
1、什么是Token验证?
Token是一种用户身份的验证方式,通常叫做令牌验证。当用户第一次登录成功后,服务器会生成一个Token并将此Token返回给用户,以后用户只需要带上这个Token前来请求数据即可,无需再用用户名和密码。
2、Token验证过程
①首次登录时,客户端通过用户名与密码请求登录
②服务端收到请求并验证用户名与密码
③若验证通过,服务端会签发一个Token,该Token会保存在服务端的数据库中,并且也会返回给客户端
④客户端收到Token并存储起来,比如放在Cookie,SessionStorage,LocalStorage。
⑤客户端每次向服务端请求资源时都会带着Token
⑥服务端收到请求,然后验证客户端请求里面带着的Token,即将客户端的Token与本地数据库中的Token作对比,如果两个Token相同,说明用户曾登录成功过,则验证通过,服务端向客户端返回请求数据。
⑦若两个Token不同,则验证不通过,需要通过用户名和密码进行登录
3、为什么使用Token验证?
当客户端多次向服务端请求数据时,服务端就需要多次从数据库中查询用户名和密码并进行比对,判断用户名和密码是否正确匹配,并作出相应提示。查询数据库是比较消耗资源的,这样无疑会增加服务器的运行压力。为了既能够验证用户登录情况又能够减轻服务器的压力,便引入了Token验证。Token一般是保存在内存中,这样的话就不用查询数据库,减少了频繁的查询数据库,使服务器更加健壮。
按照每天存放的数据以及是否按天分区可以分为增量表,全量表和快照表
项目 | Value | a |
-------- | ----- ||
电脑 | $1600 ||
手机 | $12||
导管 | $1| |
全量表 | 增量表 | 快照表 | |
---|---|---|---|
数据 | 包含到前一天的全量数据 | 前一天的增量数据 | 包含到前一天的 全量数据 |
分区 | 不分区(ymd为当前日期) | 按照每一天分区 | 按照每一天分区 |
具体查看:
https://blog.csdn.net/Jun2613/article/details/106688930
另外full outer join