我如何检查一个标识符是 dunder 还是 class-private(即会被损坏)?
How can I check if an identifier is dunder or class-private (i.e. will be mangled)?
我正在编写一个提供有关变量名称建议的项目,我希望它能够判断某个名称是否与 reserved classes of identifiers 中的任何一个相匹配。第一个(“private”)非常简单,只是 name.startswith('_')
,但是 dunder 和 class-private 名称更复杂。有没有内置函数可以告诉我?如果不是,Python 使用的内部规则是什么?
对于 dunder,检查 name.startswith('__') and name.endswith('__')
不起作用,因为那会匹配 '__'
。也许像 ^__\w+__$
这样的正则表达式可以工作?
对于 class-private,name.startswith('__')
不起作用,因为 dunder 名称没有被破坏,也没有像 '___'
这样只有下划线的名称。所以看起来我必须检查名称是否以两个下划线开头,不以两个下划线结尾,并且至少包含一个非下划线字符。那正确吗?在代码中:
name.startswith('__') and not name.endswith('__') and any(c != '_' for c in name)
我最关心的是边缘情况,所以我想确保我的规则 100% 正确。我读了 What is the meaning of single and double underscore before an object name?,但没有足够的细节。
这是内部规则。请注意,我几乎看不懂 C,所以对此持保留态度。
邓德
基于 is_dunder_name
in Objects/typeobject.c
(使用 Python 3.7 中的 str.isascii
):
len(name) > 4 and name.isascii() and name.startswith('__') and name.endswith('__')
或者,正则表达式 ^__\w+__$
可以工作,但需要启用 re.ASCII
以确保 \w
仅匹配 ASCII 字符。
Class-私有
基于_Py_Mangle
in Python/compile.c
:
name.startswith('__') and not name.endswith('__') and not '.' in name
尽管严格来说,带点的名称是“属性引用”,而不是名称,因此您可以删除该检查:
name.startswith('__') and not name.endswith('__')
这符合 Identifiers (Names).
下文档中的规则
(旁注:我没有意识到,但 not name.endswith('__')
确保该名称至少包含一个非下划线。)
我正在编写一个提供有关变量名称建议的项目,我希望它能够判断某个名称是否与 reserved classes of identifiers 中的任何一个相匹配。第一个(“private”)非常简单,只是 name.startswith('_')
,但是 dunder 和 class-private 名称更复杂。有没有内置函数可以告诉我?如果不是,Python 使用的内部规则是什么?
对于 dunder,检查 name.startswith('__') and name.endswith('__')
不起作用,因为那会匹配 '__'
。也许像 ^__\w+__$
这样的正则表达式可以工作?
对于 class-private,name.startswith('__')
不起作用,因为 dunder 名称没有被破坏,也没有像 '___'
这样只有下划线的名称。所以看起来我必须检查名称是否以两个下划线开头,不以两个下划线结尾,并且至少包含一个非下划线字符。那正确吗?在代码中:
name.startswith('__') and not name.endswith('__') and any(c != '_' for c in name)
我最关心的是边缘情况,所以我想确保我的规则 100% 正确。我读了 What is the meaning of single and double underscore before an object name?,但没有足够的细节。
这是内部规则。请注意,我几乎看不懂 C,所以对此持保留态度。
邓德
基于 is_dunder_name
in Objects/typeobject.c
(使用 Python 3.7 中的 str.isascii
):
len(name) > 4 and name.isascii() and name.startswith('__') and name.endswith('__')
或者,正则表达式 ^__\w+__$
可以工作,但需要启用 re.ASCII
以确保 \w
仅匹配 ASCII 字符。
Class-私有
基于_Py_Mangle
in Python/compile.c
:
name.startswith('__') and not name.endswith('__') and not '.' in name
尽管严格来说,带点的名称是“属性引用”,而不是名称,因此您可以删除该检查:
name.startswith('__') and not name.endswith('__')
这符合 Identifiers (Names).
下文档中的规则(旁注:我没有意识到,但 not name.endswith('__')
确保该名称至少包含一个非下划线。)