【问题标题】:What is the type of a parameter that is an abstract class name in Python docstrings?Python 文档字符串中作为抽象类名的参数的类型是什么?
【发布时间】:2018-12-28 09:38:45
【问题描述】:

已编辑:假设我有一些继承自 SuperFoo 抽象类的类:

from abc import ABCMeta, abstractmethod

class SuperFoo(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def do_something():
        pass

class Foo(SuperFoo):
    def __init__(self):
        pass

    def do_something():
        pass

class Bar(SuperFoo):
    def __init__(self):
        pass

    def do_something():
        pass

还有一个以SuperFoo 的子类作为参数的文档化函数:

def build(super_foo):
    """
    Instantiate a SuperFoo class and do some other stuff.
    @param super_foo: The subclass whose constructor will be called
    @type super_foo: ??? <--- What to use here?
    @return: An instance of a SuperFoo subclass
    @rtype: SuperFoo
    """
    # Do some stuff

    instance = class_name()  # Instantiate class
    return instance

foo = build(Foo)
bar = build(Bar)

我应该在函数的文档字符串中使用什么@type?它不能是SuperFoo,因为它对应于SuperFoo 的一个实例,而不是类型本身。

【问题讨论】:

  • 1) Python 中的一切都是对象。 2) 它的类型实际上就是... type.
  • A name 将是一个字符串,例如"Foo"。你实际上是在传递一个 object.
  • 在 python 中,一切都是对象。话虽如此,当我们在您的示例 Foo 中编写一个类时,python 中的所有类都继承了元类类型。 @type 表示您传递的类应该是继承 Meta Class 类型的类。要检查此行为,请尝试运行 type(Foo) >>> 。我希望我能解释你的问题
  • 不是类名本身。它是类对象本身
  • @GerardoFigueroa 和 object 实例不可调用。 object 类当然是可调用的。所有类都是可调用的,这就是你如何实例化它们。

标签: python class types docstring


【解决方案1】:

motyzk 已经发布了简单的技术答案 - 在您的示例中,您传递给 build 的是类,因此(名称错误的)class_name 参数的类型为 type - 具有以下限制(基于您的代码 sn-p)此类不应期望任何参数,该参数不对应于任何明确定义的现有内置“类型”。

现在在 cmets 中提到,在 Python 中

  • 一切都是对象(并且是类的实例),
  • 实例化类是通过调用类对象来完成的,就像调用任何函数一样,
  • 所有可调用对象都返回一个对象,即使是隐含的(None 也是一个对象)

所以您的 build 函数在技术上与不期望参数的 any 可调用函数相同。例如,这个:

def bar():
   return

whatever = build(bar)

在技术上是正确的。

现在你在函数的文档字符串中提到(重点是我的):

实例化一个类并做一些其他的事情

由于您发布的 sn-p 中显示您的函数完全没用,我假设在您的 real 代码中,重要的部分是(未显示)“做一些其他的事情”,并且这个“做一些其他的事情”部分依赖于被传递的类的某些特定属性。

在这种情况下,您应该以非正式的方式(以文本形式,在文档字符串本身中)或formally using the abc module 记录这些特性。这实际上并不能解决你的问题——你的函数需要一个类,而不是实例,所以理论上@type 应该是type(YourABC),但是你得到的是abc.ABCMeta。此时,您要么必须编写一个自定义元类(继承自 abc.ABCMeta)并将其指定为正确的 @type - 但这不会说明任何有用的文档 - 或者只是将其描述为“ MyABC 子类”(这是正确的描述,但不能用于代码检测)。

【讨论】:

  • 感谢您的澄清。我编辑了问题以表明该参数是抽象类SuperFoo 的子类,因此type 在这里过于宽泛。
  • 但如果我执行@type super_foo: SuperFoo,函数将期望SuperFoo 的实例,而实际上它应该期望SuperFoo 类型。 IDE 也会抱怨。
  • Duh - 你当然是对的 - 函数期望的是 SuperFoo 子类,而不是 SuperFoo 实例,我的错(我认为是喝咖啡的时间 )。
  • 我再次编辑了我的答案。我很抱歉不得不说我在这里想不出任何正式的明确答案......如果它 only 用于文档,只需说明“@type: a SuperFoo subclass is more than够了。Python 是一种动态语言,几十年来一直使用“隐含接口”(即“类文件对象”或“类 dict 对象”,所以“A SuperFoo 子类”比你会发现的更明确在大多数文档中。
【解决方案2】:

类型是“类型”,可以看出,运行这个:

class Foo(object):
    def __init__(self):
        pass


def f(t):
    print(type(t)) # <class 'type'>

f(Foo)

【讨论】:

  • 这个答案以及我的评论和布鲁诺。能正确解释这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-20
  • 2016-11-30
  • 2012-09-13
相关资源
最近更新 更多