gpt4 book ai didi

python - 如何在子类中键入注释重写的方法?

转载 作者:太空狗 更新时间:2023-10-30 02:57:39 26 4
gpt4 key购买 nike

假设我已经有了一个带有类型注释的方法:

class Shape:
def area(self) -> float:
raise NotImplementedError

然后我将多次子类化:

class Circle:
def area(self) -> float:
return math.pi * self.radius ** 2

class Rectangle:
def area(self) -> float:
return self.height * self.width

如您所见,我重复了很多 -> float。假设我有 10 种不同的形状,有多种这样的方法,其中一些也包含参数。有没有一种方法可以从父类中“复制”注释,类似于 functools.wraps() 对文档字符串所做的那样?

最佳答案

这可能有效,但我肯定会错过边缘情况,例如附加参数:

from functools import partial, update_wrapper


def annotate_from(f):
return partial(update_wrapper,
wrapped=f,
assigned=('__annotations__',),
updated=())

这将从 f.__annotations__ 分配“wrapper”函数的 __annotations__ 属性(请记住,它不是副本)。

根据文档 update_wrapper assigned 函数的默认值已经包含 __annotations__,但我明白为什么您不希望从 wrapped 中分配所有其他属性。

然后您可以将CircleRectangle 定义为

class Circle:
@annotate_from(Shape.area)
def area(self):
return math.pi * self.radius ** 2

class Rectangle:
@annotate_from(Shape.area)
def area(self):
return self.height * self.width

结果

In [82]: Circle.area.__annotations__
Out[82]: {'return': builtins.float}

In [86]: Rectangle.area.__annotations__
Out[86]: {'return': builtins.float}

作为副作用,您的方法将具有属性 __wrapped__,在本例中它将指向 Shape.area


使用类装饰器可以实现一种不太标准的方法(如果您可以调用上述 update_wrapper 标准)来完成对重写方法的处理:

from inspect import getmembers, isfunction, signature


def override(f):
"""
Mark method overrides.
"""
f.__override__ = True
return f


def _is_method_override(m):
return isfunction(m) and getattr(m, '__override__', False)


def annotate_overrides(cls):
"""
Copy annotations of overridden methods.
"""
bases = cls.mro()[1:]
for name, method in getmembers(cls, _is_method_override):
for base in bases:
if hasattr(base, name):
break

else:
raise RuntimeError(
'method {!r} not found in bases of {!r}'.format(
name, cls))

base_method = getattr(base, name)
method.__annotations__ = base_method.__annotations__.copy()

return cls

然后:

@annotate_overrides
class Rectangle(Shape):
@override
def area(self):
return self.height * self.width

同样,这不会处理带有附加参数的覆盖方法。

关于python - 如何在子类中键入注释重写的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36306834/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com