【问题标题】:Can type hints of the class be used in class functions? [duplicate]类的类型提示可以在类函数中使用吗? [复制]
【发布时间】:2017-10-05 18:41:30
【问题描述】:

是否可以在同一个类的类的方法中使用类型注解? 假设我有一个vector类,这个类支持__add__

类似这样的:

class Vector:
    def __add__(self, other: Vector):
        #blah blah

这当然行不通。还有其他类似的方法或解决方法吗?

【问题讨论】:

  • 你的问题是是否可以添加这样的类型注释,或者是否可以使用这样的类型注释来“确保参数属于同一类”?正如一些答案中提到的那样,类型注释不会强制执行任何操作,因此即使您可以进行这样的注释,它也不会“确保”这一点。
  • 我误解了类型提示,我认为这是一种可以强制类型的机制。但是对于文档,它可能很有用。我将编辑我的问题

标签: python


【解决方案1】:

类型注释旨在帮助人们阅读代码、静态分析工具和文档工具。即使可以执行您拥有的代码(我的意思是没有NameError),它实际上也不会强制执行任何操作。

在 python 中,实际执行一个特定的类通常被认为是不好的风格,你通常期望一个特定的接口(比如具有一个特定的属性):

class Vector(object):
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __add__(self, other):
        try:
            return Vector(self.x + other.x, self.y + other.y)
        except AttributeError:  # the other had no x or y attribute
            raise TypeError('cannot add Vector to {}'.format(type(other)))

或者只是省略 tryexcept 并让它与 AttributeError 一起失败:

class Vector(object):
    def __init__(self, x, y):
        self.x, self.y = x, y
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

它没有提供信息的异常消息(你需要一个吗?)但是当other 没有xy 属性时它仍然会失败。


如果我误解了您的问题,而它只是关于“如何添加类型提示”,那么您只需将其包装为字符串(称为“前向引用”):

class Vector(object):
    def __add__(self, other: 'Vector'):
        ...

他们甚至在 PEP 484 中有一个类似的例子:

Forward references

当类型提示包含尚未定义的名称时,该定义可以表示为字符串文字,稍后再解析。

这种情况经常发生的情况是定义容器类,其中被定义的类出现在某些方法的签名中。例如,下面的代码(一个简单的二叉树实现的开始)不起作用:

class Tree:
    def __init__(self, left: Tree, right: Tree):
        self.left = left
        self.right = right

为了解决这个问题,我们写:

class Tree:
    def __init__(self, left: 'Tree', right: 'Tree'):
        self.left = left
        self.right = right

【讨论】:

    【解决方案2】:

    你可以检查other是否是Vector类型:

    def __add__(self, other):
        if isinstance(other, Vector):
            ##do the add
        else:
            raise TypeError('other is not a Vector Type')
    

    【讨论】:

    • 那么没有别的办法了吗?
    • @LucasCrijns 这样做有什么问题?
    • 为一个类中的每个运算符函数实现这个看起来很麻烦,所以我想也许有更精简的方法来做到这一点
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 2020-05-20
    • 2012-08-04
    • 2020-08-02
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多