Python 3 - 使用defaultdict

时间:2017-10-25 10:27:48

标签: python python-3.x recursion defaultdict

我想在这里实现什么?

我想读取目录中的每个.txt文件并将它们存储到名为documents的defaultdict中。此defaultdict的键应该是文档的名称,其值应该是文档的内容。

请注意,某些.txt文件是同一文档的一部分(就像新闻文章的不同页面一样):在这种情况下,如果文档已经存在,我希望能够更新文档并附加.txt文件的内容在违约中。

为了做到这一点,我一直在实施这个课程:

class Document(object):
'''
    Could be an article, a letter, an interview or whatever
'''
    def __init__(self):
        self.name = None
        self.text = ''
        self.image = None

    @property 
    def name(self):
        return name

    @name.setter
    def name(self, name):
        self.name = name

    def append_text(self, text):
        self.text += ' ' + text


然后,我使用此函数遍历目录中的所有文件并创建defaultdict:

def get_documents_from(dir_path):

    documents = defaultdict(lambda: Document())

    for filename in [f for f in os.listdir(dir_path) if f.endswith('.txt')]:
        name, _ = parse_filename(filename)
        documents[name].append_text(read_txt(filename))
        documents[name].name = name

    return documents

这里,函数 parse_filename 帮助我获取正在读取的文档的名称。函数 read_text 以字符串形式返回文档内容。


当我在main.py

中执行下面的行时
my_dir = 'path/to/directory'
documents = get_documents_from(my_dir)

我收到以下错误:

File "lda_TM.py", line 17, in <module>
documents = get_documents_from(my_dir)
  File "/path/to/main.py", line 36, in get_documents_from
documents[name].append_text(read_txt(filename))
  File "/path/to/main.py", line 32, in <lambda>
documents = defaultdict(lambda: Document())
  File "path/to/Document.py", line 8, in __init__
self.name = None
  File "path/to/Document.py", line 19, in name
self.name = name
  File "path/to/Document.py", line 19, in name
self.name = name
  File "path/to/Document.py", line 19, in name
self.name = name
  [Previous line repeated 491 more times]
RecursionError: maximum recursion depth exceeded


我真的不明白为什么我会收到这个错误...是因为类文档没有正确实现,还是因为我不能使用我自己的对象和defaultdict?

我知道我可以通过使用一个简单的dict并通过每次遇到一个新名称时创建一个新文档来解决这个问题(或者如果名称已经存在则更新一个Document),但这似乎不是非常高效且有点单声道。 ..

另外,我知道创建一个defaultdict,它使用文档的名称作为键,而对象Document(已经嵌入了相同的名称)作为值可能看起来很奇怪。我只是想如果我创建了一个Document列表而不是一个dict,我将被迫实现一个搜索功能以更新Document。使用defaultdict似乎更有效(因为我会在读完所有文件后立即将其转换为List)。

非常感谢您的帮助和建议!


威廉

2 个答案:

答案 0 :(得分:2)

您的班级文档包含属性name和属性name。第二个覆盖了第一个。

当你这样做时:

@property 
def name(self):
    return name

首先,我假设有一个拼写错误,而不是return self.name,否则你会得到NameError。其次,您要返回的内容是name的值,但现在name是属性,而后者又会尝试返回name的值,依此类推。

典型的解决方案是将属性称为类似_name的属性,这样它就不会被属性隐藏。

答案 1 :(得分:0)

请参阅此答案,了解正确命名的示例:https://stackoverflow.com/a/598092

self.name = name递归调用&#39; name&#39;属性

此代码正常运行:

@property 
def name(self):
    return self._name

@name.setter
def name(self, name):
    self._name = name