为什么包含类的名称不被识别为一个返回值的功能注释? [英] Why is the name of the containing class not recognized as a return value function annotation?
问题描述
我要使用 Python函数注释来指定静态工厂方法的返回值的类型。我明白这是所需要的用例之一的注解。
I was going to use Python function annotations to specify the type of the return value of a static factory method. I understand this is one of the desired use cases for annotations.
class Trie:
@staticmethod
def from_mapping(mapping) -> Trie:
# docstrings and initialization ommitted
trie = Trie()
return trie
PEP 3107 指出:
功能注释只不过是在编译时关联任意Python前$ P $与函数的各个部分pssions的一种方式了。
Function annotations are nothing more than a way of associating arbitrary Python expressions with various parts of a function at compile-time.
特里
是在Python有效的前pression,不是吗? Python不同意或者说,找不到名称:
Trie
is a valid expression in Python, isn't it? Python doesn't agree or rather, can't find the name:
高清from_mapping(映射) - >特里:
结果
NameError:名称'特里'没有定义
这是值得注意的是,这个错误不会发生,如果基本类型(如对象
或 INT
)或一个标准库类型(如 collections.deque
)指定的。
It's worth noting that this error does not happen if a fundamental type (such as object
or int
) or a standard library type (such as collections.deque
) is specified.
是什么原因造成这个错误,我该如何解决这个问题?
推荐答案
特里
是一个有效的前pression,并评估与此名称相关的当前值名称特里
。但是,这名未被定义,然而 - 一类对象的 的类主体已运行completition后只绑定至名归。你会注意到在这个非常简单的例子相同的行为:
Trie
is a valid expression, and evaluates to the current value associated with the name name Trie
. But that name is not defined yet -- a class object is only bound to its name after the class body has run to completition. You'll note the same behavior in this much simpler example:
class C:
myself = C
# or even just
C
通常情况下,解决方法是设置类已经被定义之后,类主体以外的类属性。这不是一个很好的选择在这里,虽然它的工作原理。或者,您可以在初始定义中使用的任何占位符值,然后替换它在 __注释__
(这是合法的,因为这是一个普通的字典):
Normally, the workaround would be setting the class attribute after the class has been defined, outside the class body. This is not a really good option here, though it works. Alternatively, you could use any placeholder value in the initial definition, then replace it in the __annotations__
(which is legal because it's a regular dictionary):
class C:
def f() -> ...: pass
print(C.f.__annotations__)
C.f.__annotations__['return'] = C
print(C.f.__annotations__)
它的确实的感觉,而哈克虽然。根据您的使用情况下,有可能改为使用定点对象(如 CONTAINING_CLASS =对象()
),并离开国际preting,要什么实际处理注释。
It does feel rather hacky though. Depending on your use case, it might be possible to instead use a sentinel object (e.g. CONTAINING_CLASS = object()
) and leave interpreting that to whatever actually processes the annotations.
这篇关于为什么包含类的名称不被识别为一个返回值的功能注释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!