Python docstring 类型注释 -- class,不是实例?

Python docstring type annotation -- a class, not an instance?

假设我有:

class A(object):
   pass

class B(A):
   pass

我想声明一个以 A 的子class 作为参数的函数:

def do_something(klass):
   """
   :type klass: WHAT_HERE
   """
   pass

我应该在 WHAT_HERE 中输入什么?如果我这样做:

:type klass: A

PyCharm 认为我应该给出 A 的实例作为参数,而不是 class 本身。

所有 class 都是 type class:

的实例
>>> class Foo:
...     pass
... 
>>> type(Foo())
<class '__main__.Foo'>
>>> type(Foo)
<class 'type'>
>>> type(Foo) is type
True

所以,一个有效的答案是:

:type klass: type

根据 pycharm docs 可以得到的最接近的是:

() -> SomeClass

所以在你的例子中

def do_something(klass):
   """
   :type klass: () -> A
   """
   pass

这意味着(对于 PyCharm)您提供的参数是一个函数,returns 一个给定类型的对象。它会在对象创建后正确键入任何提示。

Guido 回答了这个问题 here,但我认为 PyCharm 没有正确支持 Python 中的适当语法 2. 我认为语法应该是 (...) -> A PyCharm 和 Python 2. 在 Python 3 中,适当的语法是 Callable[..., A].

我注意到 PyCharm 也不将 () -> A 视为 class;如果您使用此语法在 A 上调用 class 方法,PyCharm 检查将标记它找不到引用的 class 方法。

这已经 filed in the JetBrains bugtracker,但根据之前的评论已关闭。鉴于 Guido 最近在第一篇参考文献中发表的评论,我希望 JetBrains 能够重新开放。

答案是Type。如果您安装了 typing 模块,您还可以将此 class 绑定为某个对象的子 class,如下例所示:

class BaseUser(): pass        
class Admin(BaseUser): pass
class Staff(BaseUser): pass
class Client(BaseUser): pass

然后

from typing import Type, TypeVar

U = TypeVar('U', bound=BaseUser)

def new_user(user_class):
    """
    type user_class: Type[U]
    """
    return user_class()

以下是用法

new_user(Admin)
new_user(Client)
new_user(Staff)

Pycharm | IDEA 理解 typing 提示很好,所以它会成功

在 PyCharm 或 IDEA 中使用 Python 2 的文档字符串语法无法做到这一点。

但是,您可以通过在用法上方放置 assert 语句来完成变量的代码:

def call_foo(cls):
  """
  Calls the class method ``foo`` of the given class.

  :param cls: a subclass of SomeClass
  :type cls: type
  """
  assert issubclass(cls, SomeClass)
  cls.foo()  # you'll get code completion here for the foo method defined in SomeClass