• 如何优雅的生成及遍历python嵌套字典


    嵌套字典生成

    方法一:定义类

    class Vividict(dict):

    def __missing__(self, key):

    value = self[key] = type(self)()

    return value

    解释:

    • 第一行:class后面紧接着是类名,即Vividict,类名通常是大写开头的单词,紧接着是(dict),表示该类是dict类继承下来的。

    我们可以使用dir(dict)查看dict的方法

    In[22]: print(dir(dict))

    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

    同理,可以查看Vividict的方法

    In[23]: print(dir(Vividict))

    ['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__missing__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

    比较两者可以发现,Vividict的方法比dict的方法多了一个missing方法,也就是我们添加的方法。所以这就是继承,继承最大的好处是子类获得了父类的全部功能,而不必重新造轮子。

    • 第二行:python魔法方法中的自定义序列,类似于定义一个函数。missing在字典的子类中使用,它定义了当试图访问一个字典中不存在的键时的行为(目前为止是指字典的实例,例如我有一个字典 d , “george” 不是字典中的一个键,当试图访问 d[‘george’] 时就会调用 d.missing(“george”),结果为{} )。

    • 第三行,第四行:访问字典中不存在的键(key)时,返回空字典作为其返回值(value)

    例如:

    In[17]: a = dict()

    In[18]: type(a)()

    Out[18]:

    {}

    注意:

    • 特殊方法“missing”前后有两个下划线!!!
    • 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。

    使用:

    # coding=utf-8

    #导入模块

    import os, openpyxl

    import pprint

    from pandas import DataFrame

    #pprint模块可以输出漂亮的字典结构,但是不利于后期利用R作图

    #DataFrame可以将字典结构转为数据框输出,方便后期利用R作图

    #切换工作路径

    os.chdir(r'F:pycharm_projectmutation_count')

    #读取excel表格

    wb = openpyxl.load_workbook('东方肝胆数据综合.xlsx')

    sheet = wb.active

    #定义类

    class Vividict(dict):

    def __missing__(self, key):

    value = self[key] = type(self)()

    return value

    #实例化

    d = Vividict()

    #字典初始化,赋初值0

    for i in range(2,sheet.max_row+1):

    d[sheet.cell(row=i, column=1).value][sheet.cell(row=i, column=15).value] = 0

    #累加统计各个样本各种突变类型的数目

    for i in range(2,sheet.max_row+1):

    d[sheet.cell(row=i, column=1).value][sheet.cell(row=i, column=15).value] +=1

    pprint.pprint(d)

    #输出字典结构

    pprint.pprint(d)

    {'PDC1279A_vs_PDC1279': {'UTR3': 9,

    'UTR5': 4,

    'downstream': 5,

    'exonic': 149,

    'intergenic': 170,

    'intronic': 163,

    'ncRNA_exonic': 17,

    'ncRNA_intronic': 23,

    'splicing': 2,

    'upstream;downstream': 2},

    'PDC1279C_vs_PDC1279': {'UTR3': 11,

    'UTR5': 13,

    'downstream': 1,

    'exonic': 174,

    'intergenic': 189,

    'intronic': 172,

    'ncRNA_exonic': 24,

    'ncRNA_intronic': 36,

    'splicing': 4,

    'upstream': 2,

    'upstream;downstream': 2}}

    #输出数据框结构,缺损的元素用 NaN补齐

    frame = DataFrame(d)

    print(frame)

    PDC1279A_vs_PDC1279 PDC1279C_vs_PDC1279

    UTR3 9.0 11.0

    UTR5 4.0 13.0

    downstream 5.0 1.0

    exonic 149.0 174.0

    exonic;splicing NaN NaN

    intergenic 170.0 189.0

    intronic 163.0 172.0

    ncRNA_exonic 17.0 24.0

    ncRNA_intronic 23.0 36.0

    ncRNA_splicing NaN NaN

    splicing 2.0 4.0

    upstream NaN 2.0

    upstream;downstream 2.0 2.0

    方法二:使用defaultdict()

    两个维度字典:

    from collections import defaultdict

    d = defaultdict(defaultdict)

    d[1][2] = 3

    等价于:

    from collections import defaultdict

    def nested_dict_factory():

    return defaultdict(int)

    def nested_dict_factory2():

    return defaultdict(nested_dict_factory)

    db = defaultdict(nested_dict_factory2)

    当然,第一种方法简洁的多!

    要获得更多维度,你可以(三维):

    from collections import defaultdict

    d = defaultdict(lambda :defaultdict(defaultdict))

    d[1][2][3] = 4

    使用defaultdict任何未定义的key都会默认返回一个根据method_factory参数不同的默认值, 而相同情况下dict()会返回KeyError.

    python中lambda存在意义就是对简单函数的简洁表示

    实际上 defaultdict也是通过missing方法实现的。defaultdict在dict的基础上添加了一个missing(key)方法, 在调用一个不存的key的时候, defaultdict会调用missing, 返回一个根据default_factory参数的默认值, 所以不会返回Keyerror.

    In[35]: print(dir(defaultdict))

    ['__class__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__missing__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'default_factory', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

    嵌套字典的遍历

    方法一:一层一层的嵌套迭代,从而实现遍历

    for key,value in d.items():

    for key2, val2 in value.items():

    print (key2, val2)

    在类中定义walk方法实现嵌套字典的遍历

    class Vividict(dict):

    def __missing__(self, key):

    value = self[key] = type(self)()

    return value

    def walk(self):

    for key, value in self.items():

    if isinstance(value, Vividict):

    for tup in value.walk():

    yield (key,) + tup

    else:

    yield key, value

    解释:
    第1-4行:上面已经解释过了
    第5-11行:定义一个walk函数,并对字典items对象的key和value进行遍历,isinstance用于判断对象类型,如果value是一个字典,那么对value调用walk()方法继续进行遍历,一层一层将key,value存储在元祖中()。当最里面一层,即else情况,输出key,value。整个过程即将字典数据结构扁平化为元祖

    此时,我们可以这样来遍历字典(输出元祖)

    #打印整个元祖

    for tup in d.walk():

    print(tup)

    ('PDC1279_vs_PDC1279C6', 'downstream', 3)

    ('PDC1279_vs_PDC1279C6', 'UTR3', 11)

    ('PDC1279_vs_PDC1279C6', 'intronic', 164)

    ('PDC1279_vs_PDC1279C6', 'splicing', 4)

    **这就是扁平化的字典**

    #打印元祖的第3列

    for tup in d.walk():

    print(tup[2])

    参考

    (1)https://ask.helplib.com/229754

    (2)Python魔法方法指南(推荐阅读)

    http://pyzh.readthedocs.io/en/latest/python-magic-methods-guide.html

  • 相关阅读:
    redis_03 _ 高性能IO模型:为什么单线程Redis能那么快
    redis_02 _ 数据结构:快速的Redis有哪些慢操作?
    redis-01 _ 基本架构:一个键值数据库包含什么?
    mysql_28 _ 读写分离有哪些坑
    mysql_27 _ 主库出问题了,从库怎么办
    小程序的转发功能
    简单几何(求交点) UVA 11178 Morley's Theorem
    测试开发CICD——Docker——windows8上环境安装
    测试开发进阶——spring boot——MVC——MyBatis初步了解(转载)
    BZOJ 2226 [Spoj 5971] LCMSum
  • 原文地址:https://www.cnblogs.com/Javauser/p/10682726.html
Copyright © 2020-2023  润新知