问题描述
编辑
当尝试从作为实例属性的类继承时,会出现此问题。此mcve再现了它,我将以下问题留给后代:
@H_404_5@class A: class SubA: pass a = A() class B(a.SubA): pass
@H_404_5@Name 'a.SubA' is not defined
通过:
@H_404_5@class A: class SubA: pass class B(A.SubA): pass
此Related Issue中的示例与@H_404_5@Flask-sqlAlchemy在@H_404_5@db命名空间下提供声明性基类所做的工作几乎完全相同。在此问题中,@H_404_5@mypy维护者断言他们不支持该模式。
我的问题是,关于上述模式,@H_404_5@mypy将不支持它,这是不正确的吗?尤其是在@H_404_5@Flask-sqlAlchemy之类的大型项目中使用它。
此外,@H_404_5@Flask-sqlAlchemy和@H_404_5@mypy的用户在他们的项目中管理此问题的最佳方法是什么?
原始问题
这个问题不是关于缺少@H_404_5@Flask-sqlAlchemy存根的问题。接受之后,我遇到了这个问题。
请帮助我了解以下原因为何无法按预期工作。
在我的环境中,我仅安装了@H_404_5@Flask-sqlAlchemy和@H_404_5@mypy。
我为@H_404_5@mypy配置了@H_404_5@ignore_missing_imports = True。
@H_404_5@from flask_sqlalchemy import sqlAlchemy db = sqlAlchemy() class Widget(db.Model): id = db.Column(db.Integer,primary_key=True)
显示:
@H_404_5@error: Name 'db.Model' is not defined
因此,我尝试对@H_404_5@sqlAlchemy进行子类化,以为@H_404_5@Model提供注释,该注释显示在对象上的@H_404_5@__annotations__中,但对该模块进行了@H_404_5@mypy分析不变:
@H_404_5@from flask_sqlalchemy import sqlAlchemy from flask_sqlalchemy.model import DefaultMeta class TypedsqlAlchemy(sqlAlchemy): Model: DefaultMeta db = TypedsqlAlchemy() print(db.__annotations__) # {'Model': <class 'flask_sqlalchemy.model.DefaultMeta'>} class Widget(db.Model): id = db.Column(db.Integer,primary_key=True)
执行文件时,@H_404_5@print(db.__annotations__)命令显示@H_404_5@{'Model': <class 'flask_sqlalchemy.model.DefaultMeta'>},但@H_404_5@mypy仍然有相同的错误:
@H_404_5@error: Name 'db.Model' is not defined
我希望为@H_404[email protected]提供注释可以使该错误消失。
早期编辑
我最初误解了该错误,因为它并不表明@H_404_5@Model上不存在属性@H_404_5@db,它表明名称@H_404[email protected]在该名称中不存在。命名空间。但是,为什么将@H_404[email protected]当作全名,而不将@H_404_5@db当作本地定义的名称,而将@H_404_5@Model当作属性呢?这与尝试从类变量继承有关吗?
此外,我的注释不正确,应该是:
@H_404_5@class TypedsqlAlchemy(sqlAlchemy): Model: Type[DefaultMeta]
解决方法
您应该使用A.SubA
。
从mypy
的角度来看,我知道不允许通过实例变量访问嵌套类。由于A
的派生类可以覆盖嵌套类,而mypy无法识别这种情况,因此是这样的:
class A:
class SubA:
pass
class C(A):
class SubA:
pass
def foo(a: A):
class B(a.SubA): # What SubA here ?
pass
foo(C())
更新:
对于Flask-SQLAlchemy,在this讨论中建议以下解决方法:
from app import db
from sqlalchemy.ext.declarative import DeclarativeMeta
BaseModel: DeclarativeMeta = db.Model
class MyModel(BaseModel): ...
如果您正在使用flask_sqlalchemy,则可以从
flask_sqlalchemy.model import DefaultMeta
开始使用,而不是DeclarativeMeta
。