Python rtype 文档字符串/重构文本用于类工厂/选择器
: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 个回答
如果数据是某个抽象类的实例,你可以使用以下代码片段:
示例 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错误。
说到Python 3.6.9,可能会让人觉得不太舒服,但正如你自己所说的,这就是正确的写法:
"""
:return: subclass of SomeAbstractClass
:rtype: type
"""
这里的rtype是用来定义返回值的类型。我觉得这个地方没有什么好争论的。
到2020年,唯一一个能正常工作的解决方案是使用python3的注解:
这在2020年是完全可以接受的。
附上一个截图来展示正确的行为。基本上,def factory(name) -> type[SomeAbstractClass]:
或者 def factory(name) -> "type[SomeAbstractClass]":
(在无法导入名称的情况下)都能正常工作。
不过,对于旧版本的Python(也就是不使用注解的情况),我还是没找到解决办法。但在2020年这并不是个大问题。
还有相同的代码文本,如果有人想复制粘贴来测试其他方法:
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