我试图查看是否可以在defaultdict中使用构造函数,但我无法运行代码并获得递归错误。只是想知道是否有可能:
from collections import defaultdict
class TrieNode:
def __init__(self, char):
self.children = defaultdict(TrieNode(char))
self.is_word = False
a = TrieNode('b')
答案 0 :(得分:2)
在构造函数中使用defaultdict
并没有错。问题是您需要向它传递一个函数,当您添加新键时,它会调用 it 。制作字典时,当前正在调用该函数。结果,您将不断地无限拨打TrieNode('b')
。
您需要使用类似这样的名称来调用它:
self.children = defaultdict(TrieNode)
然后,当您在children
中引用未知密钥时,它将为您调用TrieNode()
。但是,这意味着您不想在构造函数中使用其他参数。
那可能没问题,因为您通常在特里添加单词,并且需要通过同一节点添加很多单词。一种选择是做类似的事情:
from collections import defaultdict
class TrieNode:
def __init__(self):
self.children = defaultdict(TrieNode)
self.is_word = False
self.val = ''
def add(self, word):
self.val= word[0]
if (len(word) == 1):
self.is_word = True
else:
self.children[word[0]].add(word[1:])
def words(self):
if self.is_word:
yield self.val
for letter, node in self.children.items():
yield from (letter + child for child in node.words())
然后可以在其中添加单词,它将使TrieNodes成为默认词典中的内容:
node = TrieNode()
node.add("dog")
node.add("catnip")
node.add("cats")
node.add("cat")
node.add("crunch")
node.children['c'].children
> defaultdict(__main__.TrieNode,
{'a': <__main__.TrieNode at 0x179c70048>,
'r': <__main__.TrieNode at 0x179c70eb8>})
您可以看到您的孩子有一个c
键,该键指向一个TrieNode,其孩子是defaultdict,a
和r
指向下一个。
这使您可以使用生成器轻松提取单词:
list(node.words())
> ['dog', 'cat', 'cats', 'catnip', 'crunch']