0

如何在 3.5 中为命名元组创建 plus 的自定义重载?我知道 3.6 中有一些新的语法,你能在 3.5 中做到吗?我也希望它通过 mypy 检查。

from typing import NamedTuple


Point = NamedTuple('Point',[('x',int),
                            ('y',int)])

def joinPoints(a: Point, b:Point) -> Point:
    return Point(x = a.x+b.x,y=a.y+b.y)

q = Point(1,2)
r = Point(3,4)
s= joinPoints(q,r)
t = q+r #HOW DO I MAKE THIS GO?
#s should equal t
4

1 回答 1

2

需要注意的是,在 Python 3.6 中用于定义类型化命名元组的新的、基于类的语法最终在运行时所做的基本上是一堆元编程 hijinkery 来创建一个自定义类,__add__如果你包含一个自定义类,它恰好也包含你的自定义方法.

由于我们在 Python 3.5 中无法使用该语法,因此您真正能做的最好的事情就是自己实现所有样板文件,恐怕。

请记住,namedtuples 基本上是一种定义简单类(即子类元组)的便捷方式,仅此而已。如果你想要更复杂的东西,你实际上需要自己实现它。


在任何情况下,完全搁置类型,没有一种超级干净的方式来做你在运行时尝试做的事情,更不用说类型了(至少,据我所知)。我想一种干净的方法是在定义 Point 类之后手动修补它,如下所示:

from typing import NamedTuple

Point = NamedTuple('Point', [('x', int), ('y', int)])

def add(self: Point, other: Point) -> Point:
    return Point(self.x + other.x, self.y + other.y)

Point.__add__ = add

a = Point(1, 2)
b = Point(3, 4)

print(a + b)  # prints 'Point(4, 6)'

但是,您将不得不放弃使用 mypy —— mypy 做了简化(通常是合理的)假设,即类的属性和类型签名在定义该类后不会改变,因此不允许分配新方法指向,因此将在最后一行抛出错误。

也许有一些更聪明的方法(也许以某种方式使用 abc 模块?)最终让您、Python 运行时和 mypy 满意,但我目前不知道这种方法。

于 2017-06-20T06:24:11.217 回答