假设我有一个这样的简单函数:
def foo(a: Any):
return a.bar + a.baz
我想将类型提示从Any
更改为建议(考虑到它是一种类型提示)需要a
提供bar
和baz
属性。 应该把它改成什么?
假设我有一个这样的简单函数:
def foo(a: Any):
return a.bar + a.baz
我想将类型提示从Any
更改为建议(考虑到它是一种类型提示)需要a
提供bar
和baz
属性。 应该把它改成什么?
# If you're using Python 3.8+
from typing import Protocol
# If you need to support older versions of Python,
# pip-install the 'typing_extensions' module and do:
from typing_extensions import Protocol
class SupportsBarBaz(Protocol):
bar: int
baz: int
class MyUnrelatedClass1:
def __init__(self, bar: int, baz: int) -> None:
self.bar = bar
self.baz = baz
class MyUnrelatedClass2:
def __init__(self, bar: int, baz: int, blah: str) -> None:
self.bar = bar
self.baz = baz
self.blah = blah
class MyUnrelatedClass3:
def __init__(self, bar: str, baz: str, blah: str) -> None:
self.bar = bar
self.baz = baz
self.blah = blah
def foo(a: SupportsBarBaz) -> int:
return a.bar + a.baz
# These both type-check, even though there's no explicit relationship
# between 'SupportsBarBaz' and these two classes
foo(MyUnrelatedClass1(1, 2))
foo(MyUnrelatedClass2(1, 2, "abc"))
# But this doesn't type-check, since 'bar' and 'baz' are both strs here
foo(MyUnrelatedClass3("a", "b", "c"))
你可以在mypy文档中找到更多使用协议的信息。该页面上的信息都符合PEP规范,因此假设其他类型检查器已完成对协议的支持,则该页面上的信息应适用于其他类型检查器。
您还可以在typeshed中的类型提示存储库中找到更复杂的使用协议的示例。
不过,我想这一切只有当您实际上打算在您的代码中使用静态分析时才有意义。如果没有,您可能可以简单地定义自定义类型别名为Any
,记录该别名的“预期”含义,并使用该别名代替完整的协议。对于静态分析/自动完成工具等目的,该别名几乎完全无用,但人们通常没有阅读注释的问题。
类型提示只能引用类,因此创建一个抽象类
import abc
class MyType(abc.ABC):
@abc.abstractproperty
def foo(self):
pass
@abc.abstractproperty
def bar(self):
pass
并声明 f(a: MyType)
foo
中的任何值都需要继承自 MyType
? - Rob Gilton@abstractproperty
现在已在标准库中被弃用。 - Rob Giltonclass Myclass():
def __init__(self, bar, baz):
self.bar = bar
self.baz = baz
def foo(a: Myclass):
return a.bar + a.baz
foo
始终采用Myclass
实例。可能有一大组潜在无关的类具有bar
和baz
属性。 - Rob Gilton
MyClass
,该类将具有这些属性? - vahverofoo
只能接受MyClass
实例,而它以前并没有受到限制。 - Rob Gilton