The following code are legal:
class MyClass:
print(lambda: MyClass())
class MyClass:
print(lambda: self())
class MyClass:
children = defaultdict(lambda: MyClass())
mc = MyClass()
print(mc.children)
cc = mc.children[0]
print(cc.children)
However, the following code are illegal:
class MyClass:
def f(): return MyClass()
print(f()) #=> NameError: name 'MyClass' is not defined
class MyClass:
children = MyClass() #=> NameError: name 'MyClass' is not defined
class MyClass:
children = self() #=> NameError: name 'self' is not defined
My question is, why do MyClass
and self
become defined
once wrapped in lambda?
(I was playing with Trie structure and trying to understand why TrieNode is necessarily defined as a separate class. TrieNode is basically a one line class defined with children = defaultdict(lambda: TrieNode())
)
The factory function passed to the defaultdict
in:
class TrieNode:
children = defaultdict(lambda: TrieNode())
is not called during the class definition. Once the class is defined, the function has access to the class name from the enclosing namespace. The following will fail with a similar error you encountered:
class TrieNode:
children = defaultdict(lambda: TrieNode())
children[4] # calls factory function before class is defined!
NameError: name 'TrieNode' is not defined
An even more dramatic example for illustrating the enclosing namespace fact:
class TrieNode:
children = defaultdict(lambda: TrieNode())
t = TrieNode()
TrieNode = int
t.children[5]
# 0
# [sic!] ...
# ... t is still a TrieNode from the earlier class definiton,
# but the factory function uses the latter override from the enclosing namespace