【问题标题】:Can attributes replace properties in a Protocol or superclass and if not why not?属性可以替换协议或超类中的属性吗?如果不能,为什么不能?
【发布时间】:2021-10-09 13:11:39
【问题描述】:

我有点困惑,为什么我会在 Pycharm 中收到关于用属性替换属性的警告。

例如:

from typing import Protocol

class Foo(Protocol):
    @property
    def x(self) -> int:
        pass

class Bar(Foo):
    # I get a warning for the line below
    # Type of 'x' is incompatible with 'Foo' 
    x: int

    def __init__(self, x: int):
        self.x = x

我不明白为什么我会收到警告。在我看来,它看起来像是一个假阳性。据我所知,唯一实际的区别是Bar.x 可以分配给Foo.x 不能分配的位置。但是添加诸如添加方法之类的功能通常不会违反协议。

我在这里缺少什么?用属性替换属性真的与协议或超类不兼容吗?如果是,为什么?

【问题讨论】:

  • 请注意,您没有在Bar.__init__ 中包含self 参数;我认为错误消息告诉您intFoo 本身不兼容,而不是Foo.xBar.x 之间存在差异。
  • @chepner 哎呀。这就是在不通过代码编辑器的情况下将 SSCCE 键入堆栈溢出的危险。我已经更正了这个问题。
  • property-valued 类属性和实例属性之间仍然存在显着差异,所以我怀疑这是相关的。我想知道mypy 是否只是对Bar().x 的最终结果做出了比 PyCharm 更多的推断。
  • @chepner 除了在分配给属性时引发异常之外,如果您以其他方式与属性交互,我想不出任何会“行为不端”的交互。违反协议某些行为不得符合,但我正在绞尽脑汁想知道它可能是什么。
  • 动态语言中的静态类型提示很难。

标签: python pycharm type-hinting


【解决方案1】:

(更新:原始代码丢失了self,在这种情况下mypy 报告的类似错误使它看起来不仅仅是一个错字。)


您没有正确定义Bar.__init__x 被解释为接收Bar 实例作为其值的参数,但您已使用int 对其进行注释。

class Bar(Foo):
    x: int

    def __init__(self, x:int):
        self.x = x

问题主要出在 PyCharm 的错误信息上。 mypy 通过指出 self 丢失或输入错误来捕捉到这一点。

【讨论】:

  • 这显然是问题中的一个错字。它没有解释为什么我指定的行上的警告。即使有更正的self,问题警告仍然存在。
  • 那么这似乎是 PyCharm 的类型检查器中的一个错误。我最初发表了关于Foo.x (property) 和Bar.x(不存在,但解释为实例属性的类型)的不同类型的评论,但我不确定这是否相关。
  • mypy在您的原始代码上报告的错误消息与您报告的错误非常相似,我认为缺少self是原因。)
  • 很公平。尽管在这种情况下我确实指定了 Pycharm ;-)。欢迎您提供任何线索。很高兴知道其他编辑器/linter 没有报告这一点。
  • 我自己不使用 PyCharm,但仅根据这里有关它的问题数量,我认为它不是非常可靠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2018-05-21
  • 1970-01-01
  • 2011-12-29
  • 1970-01-01
  • 2017-05-09
相关资源
最近更新 更多