![](/img/trans.png)
[英]Python3 - How does one define an abstract subclass from an existing abstract class?
[英]Is there an "Addable" protocol or abstract base class in Python? If not how would one define it?
据我所知,没有预定义的Addable
协议。 你可以自己定义一个:
from typing import Protocol, TypeVar
T = TypeVar("T")
class Addable(Protocol):
def __add__(self: T, other: T) -> T: ...
该协议要求被加数和结果共享一个共同的祖先类型。
然后可以按如下方式使用该协议:
Tadd = TypeVar("Tadd", bound=Addable)
def my_sum(*args: Tadd, acc: Tadd) -> Tadd:
res = acc
for value in args:
res += value
return res
my_sum("a", "b", "c", acc="") # correct, returns string "abc"
my_sum(1, 2, 6, acc=0) # correct, returns int 9
my_sum(1, 2.0, 6, acc=0) # correct, returns float 9.0
my_sum(True, False, False, acc=False) # correct, returns bool 1 (mypy reveal_type returns bool, running it in python leads to result 1)
my_sum(True, False, 1, acc=1.0) # incorrect IMHO, but not detected by mypy, returns float 3.0
my_sum(1, 2, 6, acc="") # incorrect, detected by mypy
my_sum(1, 2, "6", acc=0) # incorrect, detected by mypy
您可以使用abc 模块自己定义一个。 那里提供的 ABC 元类允许您定义一个__subclasshook__
,您可以在其中检查 class 方法,例如__add__
。 如果这个方法是为某个 class 定义的,那么它就被认为是那个 abc 的子类。
from abc import ABC
class Addable(ABC):
@classmethod
def __subclasshook__(cls, C):
if cls is Addable:
if any("__add__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
class Adder():
def __init__(self, x):
self.x = x
def __add__(self, x):
return x + self.x
inst = Adder(5)
# >>> isinstance(inst, Addable)
# True
# >>> issubclass(Adder, Addable)
# True
存在这样的协议。 只是不在通常执行的代码中......存在一个特殊的 package 称为typeshed
,类型检查器使用它向未使用任何类型提示实现的代码添加类型提示...... typeshed
package 没有虽然在运行时存在。
所以你可以在类型检查期间使用_typeshed.SupportsAdd
- 但要在执行期间检查你需要动态检查__add__
方法或者你自己实现SupportsAdd
协议......
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from _typeshed import SupportsAdd
# SupportsAdd must always be written in quotation marks when used later...
def require_adding_str_results_in_int(a_obj: "SupportsAdd[str, int]"):
# the type checker guarantees that this should work now
assert type(a_obj + "a str") == int
# to check during runtime though you'd probably use
assert hasattr(a_obj, "__add__")
希望有所帮助...很可能这是实现您自己的协议和使用@runtime_checkable
装饰器的最佳方式。 您可以查看 typeshed 的源代码以获取灵感。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.