Pycharm中用于动态生成类的类型提示

eni9jsuy  于 4个月前  发布在  PyCharm
关注(0)|答案(2)|浏览(86)

当我通过Python type( )函数使用一个动态创建的类时,我试图让Pycharm的linter停止抱怨。
是的,像这样处理类对象是很奇怪的,但是在真实的代码中,这是有意义的(SQLAlchemy ORM类,如果你好奇的话)。

class MyClass(object):
    ID_NUM: int = 0

    def __init__(self, id_num: int, first_name: str, last_name: str):
        self.ID_NUM = id_num
        self.first_name = first_name
        self.last_name = last_name

def make_augmented_class(cls):
    def augmented__eq__(self, other):
        try:
            return self.id_num == other.id_num
        except AttributeError:
            return False

    new_cls = type('{}Augmented'.format(cls.__name__), tuple([cls]), {})
    new_cls.__eq__ = augmented__eq__
    return new_cls

def do_stuff(my_class):
    print(my_class.ID_NUM)

if __name__ == '__main__':
    do_stuff(MyClass)

    augmented_class = make_augmented_class(MyClass)
    do_stuff(augmented_class)  # <=== PYCHARM CODE LINTER COMPLAINS THAT "Type 'type' doesn't have expected attribute 'ID_NUM'"

字符串
我已经尝试了do_stuff( )函数的几个类型提示,比如def do_stuff(my_class: type):def do_stuff(my_class: MyClass):,但这只会导致不同的linter警告。
代码工作,但我想以某种方式消除linter警告.

ubof19bj

ubof19bj1#

使用type函数来为你的用例创建一个类并没有什么好的理由。相反,只需在函数的闭包中创建一个新的类,并返回class对象,这样linter就可以更容易地推断出这个新的类是给定类的子类。也就是说,我发现你仍然需要输入hint参数和函数的返回值,以便PyCharm不会抱怨:

from typing import TypeVar

T = TypeVar('T')

def make_augmented_class(cls: type[T]) -> type[T]:
    class _AugmentingWrapper(cls):
        def __eq__(self, other):
            try:
                return self.ID_NUM == other.ID_NUM
            except AttributeError:
                return False
    return _AugmentingWrapper

字符串

gmol1639

gmol16392#

PyCharm不太能够处理动态构造的类(可以理解,这样的动态系统很难或不可能分析)。
但是,您可以注解make_augmented_class来消除此警告,并使用小cast来告诉PyCharm信任您:

def make_augmented_class(cls: type[T]) -> type[T]:
    def augmented__eq__(self, other):
        try:
            return self.id_num == other.id_num
        except AttributeError:
            return False

    new_cls = type('{}Augmented'.format(cls.__name__), tuple([cls]), {})
    new_cls.__eq__ = augmented__eq__
    return cast(type[T], new_cls)

字符串
(有趣的是,mypy抱怨了对__eq__的赋值,而PyCharm没有。然而,我相信mypy在see GH issue这里是错误的,所以用type: ignore静默那行是一个不错的做法。或者你可以把它移到type的第三个参数中)

相关问题