PyCharm 无法识别没有冗余 __init__ 的 SqlAlchemy 声明性子类签名

Posted

技术标签:

【中文标题】PyCharm 无法识别没有冗余 __init__ 的 SqlAlchemy 声明性子类签名【英文标题】:PyCharm doesn't recognize SqlAlchemy declarative subclass signature without redundant __init__ 【发布时间】:2021-04-19 21:51:24 【问题描述】:

我有一个 SqlAlchemy 声明性基类,从该基类派生出更复杂的类,但我还需要作为基类“普通”实例的实例。我知道 SqlAlchemy 默认情况下不会创建 __init__ 方法,但基类确实有一个。尽管如此,至少 PyCharm 的 linter 似乎并没有像我期望的那样摸索:它抱怨它不识别子类实例初始化参数。

如果我正确理解/使用多态标识,当我查询基类表时,我会看到任何从与查询匹配的基类派生的东西。与其通过检查类型或其他东西来区分“普通”实例,不如将它们放在一个单独的简单派生类中,只引入一个新的类名、表名和多态标识名。

这就是解释为什么我对基类和“普通”子类有如下声明性定义的所有背景。

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class GenericFoo(Base):
    __tablename__ = 'generic_foo'
    __mapper_args__ = 'polymorphic_identity': 'generic_foo'

    def __init__(self, name, color):
        self.name = name
        self.color = color

class SpecificFoo(GenericFoo):
    __tablename__ = 'specific_foo'
    __mapper_args__ = 'polymorphic_identity': 'specific_foo'

    # If I uncomment this the linter complaint goes away.
    # def __init__(self, name, color):
    #     super(SpecificFoo, self).__init__(name, color)

# PyCharm flags "Unexpected argument" on this statement.
foo = SpecificFoo(name='bob', color='blue')

# - - - - - - - - - - - - - - - - - - - - - - - -
# "Standard" definitions for comparison:
# - - - - - - - - - - - - - - - - - - - - - - - -
class GenericBar(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color

class SpecificBar(GenericBar):
    pass

# This is of course fine.
bar = SpecificBar(name='bob', color='blue')

如注释行中所述,如果我在 SpecificFoo 中省略了看似多余的 __init__ 方法,PyCharm 会将 foo 实例化标记为无法识别的参数。如果我将 __init__(self, name, color) 方法添加到仅调用 super(SpecificFoo, self).__init__(name, color)SpecificFoo,PyCharm 很高兴。

代码似乎执行没有错误,虽然我还没有尝试过任何可能会用到它的东西。我不喜欢为了让 linter 开心而添加一个完整的冗余方法。但我担心 PyCharm 知道一些我不知道的事情,并且这里有一个错误会在以后让我伤心。知道为什么 PyCharm 会标记这一点,以及是否确实有办法满足它(大概没有多余的 __init__ 方法)?

【问题讨论】:

可能重复:***.com/q/58936116/2144390 Gord,该问题涉及 mixins,并且接受的答案指出“PyCharm 在使用 mixins 时无法将列名识别为参数。”大概是一个不同的问题? 如果您点击 YouTrack 问题的链接,会有更多讨论。 尝试关注youtrack.jetbrains.com/issue/PY-28663... 上下文不同,我很难理解。足够相似,听起来确实是相同或相关的问题。 我将此示例添加到该线程以进行澄清。 【参考方案1】:

如果您想不费吹灰之力地解决问题,可以在更新的 python 版本上使用类型提示。

定义类时,只需将类型提示:db.Column 直接放入声明中即可:

class GenericFoo(Base):
    __tablename__ = 'generic_foo'

    id: db.Column = db.Column(db.Integer, primary_key=True)
    name: db.Column = db.Column(db.String, unique=True, nullable=False)

如果对所有表都执行此操作,结果确实有点冗长,但它也将完全适用于所有 linter,而不仅仅是 PyCharm。

【讨论】:

以上是关于PyCharm 无法识别没有冗余 __init__ 的 SqlAlchemy 声明性子类签名的主要内容,如果未能解决你的问题,请参考以下文章

Pycharm无法识别__init__里import的包,ctrl时无法跳转

为什么类“QuoteClientFactory”没有被理解为pycharm中的定义?

Python包中__init__.py作用

__init__ 中的 Pycharm 类型提示不起作用

PyCharm 在 __init__.py 中找不到任何 OpenCV 函数的引用

PyCharm中Dictionary与Python package的区别