我试图修改一些用于下载和解析SEC文件的基本代码,但是在解析标题时已经完成了一些我觉得完全令人费解的事情。我不明白在下面代码的字典创建和标题分配中发生了什么:
if(file_exists($destinationFile)){
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$destinationFile = $destinationDir.'/'.sha1_file($file['tmp_name']).time().'.'.$ext;
}
目标是解析这样的文件:http://www.sec.gov/Archives/edgar/data/356213/0000898430-95-000806.txt
并返回一个元组,其中包含一个字典字典作为"标题"以及" docs"中的词典列表。大部分内容对我来说都很简单。打开文件,逐行阅读,并生成一些控制流程,告诉函数它是在文档的标题部分还是文档的文本部分。我也理解最后的列表创建算法,它附加了所有的" docdata"在一起。
然而标题部分让我大吃一惊。我或多或少地理解头解析器如何根据每个块项之前的选项卡数创建字典嵌套,然后确定每个键的位置。我不明白的是它是如何填充到#34;标题"变量。它似乎是为标准分配标题,这似乎完全倒退到我。程序将标题定义为顶部的空字典,然后对于每一行,分配将此空字典分配给curdict,然后向前发送。然后它返回看起来从未被正式操作的标题。
我猜这是我完全不了解对象分配在Python中是如何工作的。我确定它非常明显,但我还没有足够的进步能够看到以这种方式编写的程序。
答案 0 :(得分:1)
headers
是一个嵌套的字典树。分配给curdict
的循环在此树中下降到第N级,使用headerstack[i]
作为每个级别的键。首先将curdict
初始化为顶级headers
,然后在每次迭代时根据headerstack
中的下一项将其重置为子词典。
在Python中,与大多数OO语言一样,对象分配是通过引用而不是通过复制。因此,一旦完成对curdict
的最终赋值,它就会包含对其中一个嵌套字典的引用。然后当它:
curdict[sline.split('\t')[0]]=sline.split('\t')[-1]
它填充了字典元素,它仍然是headers
引用的完整树的一部分。
例如,如果headerstack
包含['a', 'b', 'c', 'd']
和level = 3
,则循环会将curdict
设置为对headers['a']['b']['c']
的引用。如果sline
为foo\tbar
,则上述分配将等同于:
headers['a']['b']['c']['foo'] = 'bar';
我将逐步展示这是如何发生的。在循环开始时,我们有:
curdict == headers
在循环的第一次迭代中:
i = 1
curdict = curdict[headerstack[i]]
相当于:
curdict = headers['a']
在下一次迭代中:
i = 2
curdict = curdict[headerstack[i]]
相当于:
curdict = curdict['b']
相当于:
curdict = headers['a']['b']
在下一个(最后)循环中:
i = 3
curdict = curdict[headerstack[i]]
相当于:
curdict = curdict['c']
是:
curdict = headers['a']['b']['c']
因此,curdict
指的是headers['a']['b']['c']
所做的相同字典。您在curdict
中对字典所做的任何操作也会发生在headers
中的字典中。所以当你这样做时:
curdict['foo'] = 'bar'
它等同于:
headers['a']['b']['c']['foo'] = 'bar'