Kho*_*ono 13 python dictionary autovivification
在寻找使用嵌套字典的方法时,我发现nosklo发布了以下代码,我想解释一下.
class AutoVivification(dict):
"""Implementation of perl's autovivification feature."""
def __getitem__(self, item):
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
Run Code Online (Sandbox Code Playgroud)
测试:
a = AutoVivification()
a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6
print a
Run Code Online (Sandbox Code Playgroud)
输出:
{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
Run Code Online (Sandbox Code Playgroud)
我是一个非常新手的程序员.我在自己的时间里学到了大部分我所知道的知识,我在高中时只接受过Turbo Pascal的正式训练.我理解并能够以简单的方式使用类,例如使用__init__类方法,并在类的实例中存储数据foo.man = 'choo'.
我不知道方括号系列如何正确地通过类(我假设它们__getitem__以某种方式调用)并且不明白它们如何被如此简洁地处理而不必单独调用该方法三次.
我的印象是(dict),班级声明中的处理方式是由__init__.
我以前用过的try: except:方式非常简单.它看起来像是在try运行时调用一系列函数__getitem__.我知道如果当前级别的字典存在,则try将通过并转到下一个字典.的except,我推测,运行有一个时候KeyError,但我还没有看到self使用过这样的. Self我被认为self是字典,而我认为是class AutoVivification......的一个实例?我从来没有像这样连续两次分配,foo = man = choo但怀疑value是指向self[item]同时self[item]指向结果type(self).但type(self)会返回这样的东西:<class '__main__.AutoVivification'>不是吗?我不知道最后有什么额外的圆括号.因为我不知道如何调用函数,我不明白value返回的位置.
抱歉有这些问题!有这么多,我不明白,我不知道在哪里查阅,只需阅读文档几个小时,我保留很少.这段代码看起来像是为了我的目的,但我想在使用之前理解它.
如果你想知道我在我的程序中尝试使用嵌套字典做什么:我试图以天文数字的形式保存地图数据.虽然我无法创建嵌套4次的10 ^ 6项的字典/列表(也就是10 ^ 24项!),但空间大部分都是空的,所以我可以完全保留空值,只有在那里有东西时才分配.困扰我的是处理字典的有效方式.
Mar*_*ers 19
逐行:
class AutoVivification(dict):
Run Code Online (Sandbox Code Playgroud)
我们创建了一个子类dict,因此AutoVivification是一种dict局部变化.
def __getitem__(self, item):
Run Code Online (Sandbox Code Playgroud)
每当有人试图通过索引查找访问实例上的项时,就会调用该__getitem()__钩子[...].所以每当有人这样做object[somekey],都会type(object).__getitem__(object, somekey)被召集.
我们try稍等一下,下一行是:
return dict.__getitem__(self, item)
Run Code Online (Sandbox Code Playgroud)
这将调用未绑定的方法__getitem__(),并将自己的实例与密钥一起传递给它.换句话说,我们所说的原来 __getitem__我们的父类定义dict.
现在,我们都知道如果item字典中没有键,会发生什么KeyError.这就是try:,except KeyError组合进来:
try:
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
return value
Run Code Online (Sandbox Code Playgroud)
因此,如果当前实例(它是子类型dict)没有给定键,它将捕获KeyError原始dict.__getitem__()方法抛出的异常,而是创建一个新值,将其存储self[item]并返回该值.
现在,请记住它self是(子类)dict,所以它是一个字典.因此,它可以分配新的值(它将使用__setitem__钩子,在其中使用钩子),在这种情况下,它创建一个与之相同类型的新实例self.那是另一个dict子类.
那么当我们打电话时会发生什么a[1][2][3] = 4呢?Python经历了这一步:
a[1]导致type(a).__getitem__(a, 1).捕获的自定义__getitem__方法,创建一个新实例,存储在键下并返回它.AutoVivificationKeyErrorAutoVivification1
a[1]返回一个空AutoVivification实例.[2]在该对象上调用下一个项目访问,我们重复步骤1中发生的事情; 有一个KeyError,AutoVivification创建一个新实例,存储在2密钥下,并将新实例返回给调用者.
a[1][2]返回一个空AutoVivification实例.[3]在该对象上调用下一个项访问,我们重复步骤1(以及步骤2)中发生的事情.还有一个KeyError,的新实例AutoVivification被创建,下存储3密钥,即新的实例返回给调用者.
a[1][2][3]返回一个空AutoVivification实例.现在我们在该实例中存储一个新值4.
进入下一行代码后a[1][3][3] = 5,顶级AutoVivification实例已经有一个1键,该return dict.__getitem__(self, item)行将返回相应的值,该值恰好是AutoVivification上面步骤1中创建的实例.
从那里,[3]项目访问调用将AutoVivification再次创建一个新实例(因为该对象a[1]只有一个2键),我们再次执行所有相同的步骤.
| 归档时间: |
|
| 查看次数: |
1188 次 |
| 最近记录: |