class Node:
def append_child(self, node: Node):
if node != None:
self.first_child = node
self.child_nodes += [node]
Run Code Online (Sandbox Code Playgroud)
我该怎么办node: Node?因为当我运行它时,它说name 'Node' is not defined.
我应该只删除: Node和实例在函数内检查吗?但那我怎么能访问node的属性(我希望它是Node类的实例)?
我不知道如何在Python中实现类型转换,BTW.
mgi*_*son 21
类型检查中的"self"引用通常使用字符串完成:
class Node:
def append_child(self, node: 'Node'):
if node != None:
self.first_child = node
self.child_nodes += [node]
Run Code Online (Sandbox Code Playgroud)
这在PEP-0484 的"前向参考"部分中描述.
请注意,这不会进行任何类型检查或转换.这是一个类型提示,python(通常)完全无视1.但是,第三方工具(例如mypy)使用类型提示对代码进行静态分析,并在运行时生成错误.
1提示是内省的 - 所以你可以使用它们来构建某种运行时检查器,如果你真的想要使用装饰器等,但是python默认不这样做.
ger*_*rit 11
从Python 3.7开始,Python可以通过PEP 563实现对类型注释的推迟评估.在PEP 563下,注释__annotations__以字符串形式存储.从Python 3.7开始,您可以通过__future__指令启用它:
from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)
这使得写入成为可能:
class C:
a: C
def foo(self, b: C):
...
Run Code Online (Sandbox Code Playgroud)
从Python 4.0开始,这种行为将是正常行为.
如果您只是想知道问题的答案,请阅读mgilson 的回答。
mgilson 的答案很好地解释了如何解决 Python 的这一限制。但我认为很好地理解为什么这行不通也很重要,所以我将提供这个解释。
Python 与其他语言有些不同。在 Python 中,实际上不存在“声明”这样的东西。对于 Python 来说,代码只是代码。当你导入一个模块时,Python会创建一个新的命名空间(全局变量可以驻留的地方),然后从上到下执行模块的每一行。 def foo(args): code只是一个复合语句,它将一堆源代码捆绑在一起形成一个函数并将该函数绑定到名称foo。类似地,class Bar(bases): code创建一个类,立即执行所有代码(在一个单独的命名空间内,该命名空间保存可能由代码创建的任何类级变量,特别是包括使用 创建的方法def),然后将该类绑定到名称Bar。它必须立即执行代码,因为所有方法都需要立即创建。由于代码在名称绑定之前执行,因此您无法引用代码顶层的类。但是,在方法内部引用类是完全可以的,因为在调用方法之前该代码不会运行。
(你可能想知道为什么我们不能先绑定名称然后执行代码。事实证明,由于 Python 实现类的方式,你必须先知道哪些方法存在,然后才能创建类对象。可以创建一个空类,然后通过属性分配一次将所有方法绑定到它(实际上,您可以手动执行此操作,通过编写然后class Bar: pass执行def method1():...; Bar.method1 = method1等等),但是这会导致更复杂的实现,并且更难概念化,所以 Python 不这样做。)
用代码总结一下:
class C:
C # NameError: C doesn't exist yet.
def method(self):
return C # This is fine. By the time the method gets called, C will exist.
C # This is fine; the class has been created by the time we hit this line.
Run Code Online (Sandbox Code Playgroud)
在 Python > 3.7 中,您可以使用dataclass. 您也可以注释dataclass。
在这个特定的例子中Node引用自身,如果你运行它,你会得到
NameError: name 'Node' is not defined
Run Code Online (Sandbox Code Playgroud)
要克服此错误,您必须包括:
from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)
它必须是模块中的第一行。在 Python 4.0 及更高版本中,您不必包含annotations
from __future__ import annotations
from dataclasses import dataclass
@dataclass
class Node:
value: int
left: Node
right: Node
@property
def is_leaf(self) -> bool:
"""Check if node is a leaf"""
return not self.left and not self.right
Run Code Online (Sandbox Code Playgroud)
例子:
node5 = Node(5, None, None)
node25 = Node(25, None, None)
node40 = Node(40, None, None)
node10 = Node(10, None, None)
# balanced tree
node30 = Node(30, node25, node40)
root = Node(20, node10, node30)
# unbalanced tree
node30 = Node(30, node5, node40)
root = Node(20, node10, node30)
Run Code Online (Sandbox Code Playgroud)