【问题标题】:Use a subtype with mypy使用 mypy 的子类型
【发布时间】:2020-05-31 21:52:09
【问题描述】:

我有一个获取对象列表并打印出来的函数。

bc_directives = t.Union[
    data.Open,
    data.Close,
    data.Commodity,
    data.Balance,
    data.Pad,
    data.Transaction,
    data.Note,
    data.Event,
    data.Query,
    data.Price,
    data.Document,
    data.Custom,
]


def print_entries(entries: t.List[bc_directives], file: t.IO) -> None:
    pass

但如果我这样做:

accounts: t.List[bc_directives] = []

for entry in data.sorted(entries):
  if isinstance(entry, data.Open):
    accounts.append(entry)
    continue
accounts = sorted(accounts, key=lambda acc: acc.account)

# the attribute account does not exist for the other class.

print_entries(accounts)

这里我有一个问题。 mypy 抱怨其他类没有帐户属性。当然是这样设计的。

“Union[Open, Close, Commodity, Balance, Pad, Transaction, Note, Event, Query, Price, Document, Custom]”的“商品”项没有“账户”属性

如果我将帐户的定义更改为t.List[data.Open],当我使用print_entries 时,mypy 会报错。 (但它应该是最好的)。 那么如何使用联合的子集并让 mypy 不抱怨呢?

【问题讨论】:

    标签: python mypy


    【解决方案1】:

    你应该让print_entries 接受一个序列,而不是一个列表。这是一个简化的示例,展示了您的代码的类型安全版本:

    from typing import IO, List, Sequence, Union
    
    class Open:
        def __init__(self, account: int) -> None:
            self.account = account
    
    class Commodity: pass
    
    
    Directives = Union[Open, Commodity]
    
    def print_entries(entries: Sequence[Directives]) -> None:
        for entry in entries:
            print(entry)
    
    
    accounts: List[Open] = [Open(1), Open(2), Open(3)]
    print_entries(accounts)
    

    print_entries 接受你的指令类型的列表 的原因是因为它会在你的代码中引入一个潜在的错误——如果print_entries 要执行entries.append(Commodities()),你的列表of 帐户将不再仅包含 Open 对象,从而破坏了类型安全性。

    Sequence 是列表的只读版本,因此完全回避了这个问题,使其限制更少。 (即 List[T] 是 Sequence[T] 的子类)。


    更准确地说,我们说 Sequence 是一个协变类型:如果我们有一些子类型 C 是父类型 P 的子类(如果 P :> C),那么 Sequence 总是正确的[P] :> 序列[C]。

    相比之下,列表是不变的:List[P] 和 List[C] 彼此之间没有内在的关系,并且两者都不是彼此的子类。

    以下是泛型类型可以设计为具有的不同类型关系的表格摘要:

                  | Foo[P] :> Foo[C] | Foo[C] :> Foo[P] | Used for
    --------------------------------------------------------------------------------------
    Covariant     | True             | False            | Read-only types
    Contravariant | False            | True             | Write-only types
    Invariant     | False            | False            | Both readable and writable types
    Bivariant     | True             | True             | Nothing (not type safe)
    

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2018-12-19
      • 1970-01-01
      • 2019-08-21
      • 2019-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多