是否可以在 Python 中定义一个带点名的函数?

Is it possible to def a function with a dotted name in Python?

在问题 What does the "yield" keyword do? 中,我发现使用了一个我不认为有效的 Python 语法。这个问题很老,而且有很多选票,所以令我惊讶的是至少没有人对这个函数定义发表评论:

def node._get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
       yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
       yield self._rightchild  

我试图对这种语法进行评估:

到目前为止

失败

SyntaxError: invalid syntax

我查阅了问题中给出的link (maybe outdated),并在网上搜索了def的用法,但没有找到任何可以解释这种"dotted name"模式的内容。我正在使用 Python 3,也许这是 Python 2 的功能?

这个语法是否(或曾经)有效,如果是,那意味着什么?

不,语法无效。通过查看文档很容易证明。在Python2中,一个标识符由以下rules构成:

identifier ::=  (letter|"_") (letter | digit | "_")*
letter     ::=  lowercase | uppercase
lowercase  ::=  "a"..."z"
uppercase  ::=  "A"..."Z"
digit      ::=  "0"..."9"

在 Py3 中,除了扩展到 Unicode 字符范围外,规则大致相同。

看来作者大概是这个意思

class Node:
    ...
    def _get_child_candidates(self, ...):
        ...

在我的评论中你不能,python3 的有效标识符在 docs:

标识符(也称为名称)由以下词法定义描述。

Python 中的标识符语法基于 Unicode 标准附件 UAX-31,详细说明和更改定义如下;另请参阅 PEP 3131 了解更多详细信息。

ASCII范围内(U+0001..U+007F),标识符的有效字符与Python2.x相同:大小写字母 A 到 Z、下划线 _ 以及除第一个字符外的数字 0 到 9。

Python 3.0 引入了 ASCII 范围之外的其他字符(参见 PEP 3131)。对于这些字符,分类使用包含在 unicodedata 模块中的 Unicode 字符数据库版本。

如果您检查代码,您会发现它是原始问题中的错字:

def node._get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

这是来电者:

result, candidates = list(), [self]
while candidates:
    node = candidates.pop() # creates an instance
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    # the _get_child_candidates node is called 
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

因此在实例上调用方法 _get_child_candidates。所以真正的实际代码看起来像:

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

这是来电者:

result, candidates = list(), [self]
while candidates:
    node = candidates.pop() # creates an instance
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    # the _get_child_candidates node is called 
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result