Python rtype 文档字符串/重构文本用于类工厂/选择器

13 投票
3 回答
3704 浏览
提问于 2025-04-17 23:32

:rtype: 是用来说明返回的对象是什么类型的。

所以,当我在下面的代码片段中创建对象 obj 时,IDE(集成开发环境)会给我一个警告,提示 cls is not callable,因为IDE认为 cls 应该是 SomeAbstractClass 这个类型的一个对象,而我其实想要的是 SomeAbstractClass 本身。

IDE 的判断是对的,因为这是默认的行为。但是我该怎么告诉它我返回的是一个类,而不是类的一个实例呢?

如果我用 type 替代 SomeAbstractClass,会稍微好一点,但这并不是解决办法,因为没有更多的检查可以使用。

def class_selector(data):
    """
    :rtype: SomeAbstractClass
    :return: Return some class based on given parameters
    """
    
    return get_from.get(data.name)
cls = class_selector(data)
obj = cls(data.more_data)

与此同时,我通过在创建对象后加上 """:type: SomeAbstractClass""" 来解决这个问题,但这并不能消除警告,而且这个方法也不太干净。

顺便说一下,我说的是 Python 2.x 的情况。

3 个回答

-4

如果数据是某个抽象类的实例,你可以使用以下代码片段:

示例 1:

def class_selector(data):
    """
    return: Return the class of data
    """

    return type(data)

示例 2:

def class_selector(data):
    """
    return: Return the class of data.
    """

    return data.__class__

如果你想用数据的名字来指定一个类,可以这样做:

def class_selector(data):
   """
   return: Return a class specified by data.name
   """
   return type(globals()[data.name])  #or use globals()[data.name].__class__

而且在使用这个的时候,你应该处理一下可能出现的KeyError错误。

0

说到Python 3.6.9,可能会让人觉得不太舒服,但正如你自己所说的,这就是正确的写法:

"""
:return: subclass of SomeAbstractClass
:rtype: type
"""

这里的rtype是用来定义返回值的类型。我觉得这个地方没有什么好争论的。

1

到2020年,唯一一个能正常工作的解决方案是使用python3的注解:

这在2020年是完全可以接受的。

附上一个截图来展示正确的行为。基本上,def factory(name) -> type[SomeAbstractClass]: 或者 def factory(name) -> "type[SomeAbstractClass]":(在无法导入名称的情况下)都能正常工作。

不过,对于旧版本的Python(也就是不使用注解的情况),我还是没找到解决办法。但在2020年这并不是个大问题。

correct_behaviour

还有相同的代码文本,如果有人想复制粘贴来测试其他方法:

class SomeAbstractClass:
    property_by_class = 1
    def __init__(self):
        self.property_by_object = 1


def factory(name) -> type[SomeAbstractClass]:
    hide_it = dict()
    class ActualClassImpl(SomeAbstractClass):
        pass
    hide_it.__setitem__(name, ActualClassImpl)
    return hide_it.__getitem__(name)

if __name__ == '__main__':
    a = factory('testclass')
    by_class_should_be_ok = a.property_by_class
    by_object_should_hint_error = a.property_by_object
    just_like_none_existing_property_hints = a.property_by_object_bad


撰写回答