在类中提示类型

时间:2016-12-14 04:46:48

标签: python

class Node:
    def append_child(self, node: Node):
       if node != None:
        self.first_child = node
    self.child_nodes += [node]

我如何node: Node?因为当我运行它时,它会显示name 'Node' is not defined

我应该删除: Node并在函数内部检查实例吗? 但是,我怎样才能访问node的属性(我希望它是Node类的实例)?

我不知道如何在Python中实现类型转换,BTW。

4 个答案:

答案 0 :(得分:15)

类型检查中的“self”引用通常使用字符串完成:

class Node:
    def append_child(self, node: 'Node'):
       if node != None:
        self.first_child = node
    self.child_nodes += [node]

PEP-0484的"Forward references"部分对此进行了描述。

请注意这不会进行任何类型检查或投射。这是类型提示,python(通常)完全忽略 1 。但是,第三方工具(例如mypy)使用类型提示对代码进行静态分析,并在运行之前生成错误。

1 提示内省的 - 所以你可以使用它们来构建某种运行时检查器,如果你真的想要使用装饰器等,但python默认不这样做。

答案 1 :(得分:6)

Python 3.7和Python 4.0及以上版本

从Python 3.7开始,您可以Python通过PEP 563实现类型注释的推迟评估。在PEP 563下,注释以字符串形式存储在typedef unsigned char u8; template <u8 N> class matrix { public: matrix(std::array<std::array<int, N>, N> l); private: std::array<std::array<int, N>, N> arr; }; template <u8 N> matrix<N>::matrix(std::array<std::array<int, N>, N> l) : arr(l) {} int main() { std::array<std::array<int, 2>, 2> arr{{{{1, 2}}, {{3, 4}}}}; // this is how you have to initialize a 2d std::array matrix<2> m = {{{{{1, 2}}, {{3, 4}}}}}; // we need one more brace here since we are initialzing the matrix, which needs its own brace } 中。从Python 3.7开始,您可以通过__future__指令启用此功能:

__annotations__

这使得可以编写:

from __future__ import annotations

从Python 4.0开始,此行为将是正常行为。

答案 2 :(得分:1)

如果您只想回答问题,请阅读mgilson's answer

mgilson的回答提供了一个很好的解释,说明如何解决Python的这种限制。但我认为理解为什么这不起作用也很重要,所以我将提供解释。

Python与其他语言略有不同。在Python中,真的没有&#34;声明。&#34;声明。&#34;就Python而言,代码只是代码。导入模块时,Python会创建一个新的命名空间(全局变量可以存在的位置),然后从上到下执行模块的每一行。 def foo(args): code只是一个复合语句,它将一堆源代码捆绑在一起,并将该函数绑定到名称foo。类似地,class Bar(bases): code创建一个类,立即执行所有代码(在一个单独的命名空间内,该命名空间包含可能由代码创建的任何类级变量,尤其包括使用{创建的方法) {1}}),然后将该类绑定到名称def。它必须立即执行代码,因为需要立即创建所有方法。因为代码在绑定名称之前执行,所以您无法在代码的顶层引用该类。但是,引用方法内部的类是完全正确的,因为该代码在调用方法之前不会运行。

(您可能想知道为什么我们不能先绑定名称然后执行代码。事实证明,由于Python实现类的方式,您必须先了解哪些方法存在,之前您甚至可以创建类对象。可以创建一个空类,然后使用属性赋值将所有方法一次绑定到它(实际上,您可以通过编写Bar手动执行此操作然后执行class Bar: pass等等,但这会导致更复杂的实现,并且更难以概念化,因此Python不会这样做。)

总结代码:

def method1():...; Bar.method1 = method1

答案 3 :(得分:1)

在Python> 3.7中,您可以使用数据类。您还可以注释数据类。

在此特定示例中,Node引用了自己,您将获得它,如果运行它,您将得到

NameError: name 'Node' is not defined

要克服此错误,您必须添加:

from __future__ import annotations

它必须是模块中的第一行。在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

示例:

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)