In the question What does the "yield" keyword do?, I found a Python syntax being used that I didn't expect to be valid. The question is old and has a huge number of votes, so I'm surprised nobody at least left a comment about this function definition:
在这个问题中,“yield”关键字是做什么的?,我发现使用了一个我没有预料到有效的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
What I tried to get this sort of syntax evaluated:
我试着评估这种语法:
- assigning an attribute to a class or object
- 为类或对象分配属性
- redefining a function of an imported module
- 重新定义一个导入模块的函数
fails so far with
失败到目前为止与
SyntaxError: invalid syntax
SyntaxError:无效的语法
I looked up the link (maybe outdated) given in the question, and searched the web for the usage of def
, but I found nothing explaining this "dotted name" pattern. I'm using Python 3, maybe this is a feature of Python 2?
我查找了问题中给出的链接(可能已经过时了),并在web上搜索def的用法,但我找不到任何解释“虚线名”模式的东西。我使用的是python3,也许这是Python 2的一个特性?
Is (or was) this syntax valid, if yes what does it mean?
这个句法是有效的吗?如果是,那是什么意思?
2 个解决方案
#1
4
No, the syntax is not valid. It is easy to prove by checking the documentation. In Python 2, an identifier is constructed by the following rules:
不,语法无效。通过检查文档很容易证明。在Python 2中,标识符由以下规则构造:
identifier ::= (letter|"_") (letter | digit | "_")*
letter ::= lowercase | uppercase
lowercase ::= "a"..."z"
uppercase ::= "A"..."Z"
digit ::= "0"..."9"
In Py3 the rules are more or less the same, beside being expanded up to the range of Unicode characters.
在Py3中,规则或多或少是相同的,除了扩展到Unicode字符的范围之外。
It seems that the author probably meant something like
似乎作者的意思是这样的
class Node:
...
def _get_child_candidates(self, ...):
...
#2
2
As in my comment you cannot, the valid identifiers for python3 are in the docs:
在我的注释中,您不能,python3的有效标识符在文档中:
Identifiers (also referred to as names) are described by the following lexical definitions.
标识符(也称为名称)由以下词汇定义描述。
The syntax of identifiers in Python is based on the Unicode standard annex UAX-31, with elaboration and changes as defined below; see also PEP 3131 for further details.
Python中的标识符语法基于Unicode标准附件UAX-31,详细说明和更改如下所定义;有关更多细节,请参见PEP 3131。
Within the ASCII range (U+0001..U+007F), the valid characters for identifiers are the same as in Python 2.x: the uppercase and lowercase letters A through Z, the underscore _ and, except for the first character, the digits 0 through 9.
在ASCII范围内(U+0001. U+007F),标识符的有效字符与Python 2中的相同。x:大写和小写字母A到Z,下划线_,除了第一个字符,数字0到9。
Python 3.0 introduces additional characters from outside the ASCII range (see PEP 3131). For these characters, the classification uses the version of the Unicode Character Database as included in the unicodedata module.
Python 3.0引入了来自ASCII范围之外的其他字符(参见PEP 3131)。对于这些字符,分类使用Unicode字符数据库的版本,如unicodedata模块所包含的版本。
If you examine the code you can see it is a typo in the original question:
如果你检查一下代码,你会发现它是原始问题中的一个错误:
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
And this is the caller:
这是来电者:
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
So the method _get_child_candidates
is called on the instance. So really the actual code looks like:
因此在实例上调用方法_get_child_candidate。所以实际的代码是这样的
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
And this is the caller:
这是来电者:
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
#1
4
No, the syntax is not valid. It is easy to prove by checking the documentation. In Python 2, an identifier is constructed by the following rules:
不,语法无效。通过检查文档很容易证明。在Python 2中,标识符由以下规则构造:
identifier ::= (letter|"_") (letter | digit | "_")*
letter ::= lowercase | uppercase
lowercase ::= "a"..."z"
uppercase ::= "A"..."Z"
digit ::= "0"..."9"
In Py3 the rules are more or less the same, beside being expanded up to the range of Unicode characters.
在Py3中,规则或多或少是相同的,除了扩展到Unicode字符的范围之外。
It seems that the author probably meant something like
似乎作者的意思是这样的
class Node:
...
def _get_child_candidates(self, ...):
...
#2
2
As in my comment you cannot, the valid identifiers for python3 are in the docs:
在我的注释中,您不能,python3的有效标识符在文档中:
Identifiers (also referred to as names) are described by the following lexical definitions.
标识符(也称为名称)由以下词汇定义描述。
The syntax of identifiers in Python is based on the Unicode standard annex UAX-31, with elaboration and changes as defined below; see also PEP 3131 for further details.
Python中的标识符语法基于Unicode标准附件UAX-31,详细说明和更改如下所定义;有关更多细节,请参见PEP 3131。
Within the ASCII range (U+0001..U+007F), the valid characters for identifiers are the same as in Python 2.x: the uppercase and lowercase letters A through Z, the underscore _ and, except for the first character, the digits 0 through 9.
在ASCII范围内(U+0001. U+007F),标识符的有效字符与Python 2中的相同。x:大写和小写字母A到Z,下划线_,除了第一个字符,数字0到9。
Python 3.0 introduces additional characters from outside the ASCII range (see PEP 3131). For these characters, the classification uses the version of the Unicode Character Database as included in the unicodedata module.
Python 3.0引入了来自ASCII范围之外的其他字符(参见PEP 3131)。对于这些字符,分类使用Unicode字符数据库的版本,如unicodedata模块所包含的版本。
If you examine the code you can see it is a typo in the original question:
如果你检查一下代码,你会发现它是原始问题中的一个错误:
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
And this is the caller:
这是来电者:
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
So the method _get_child_candidates
is called on the instance. So really the actual code looks like:
因此在实例上调用方法_get_child_candidate。所以实际的代码是这样的
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
And this is the caller:
这是来电者:
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