python类名中的有效字符

Fil*_*eia 28 python metaprogramming

我正在动态创建python类,我知道在这种情况下并非所有字符都有效.

在类库中是否有一个方法可以用来清理随机文本字符串,以便我可以将它用作类名?这个或允许的字符列表将是一个很好的帮助.


关于与标识符名称冲突的补充:与@Ignacio一样,在下面的答案中指出,任何有效作为标识符的字符都是类名中的有效字符.你甚至可以毫无困难地使用保留字作为类名.但是有一个问题.如果使用保留字,则无法像其他(非动态创建的)类一样访问类(例如,通过执行globals()[my_class.__name__] = my_class).在这种情况下,保留字始终优先.

Ign*_*ams 35

Python语言参考,§2.3,"标识符和关键字"

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

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

标识符的长度不受限制.案件很重要.

  • 这是用于定义有效标识符的正则表达式:`identifier :: =(letter |"_")(letter | digit |"_")*`.(也许您想在答案中添加一些内容,以便用户不必搜索网页?) (2认同)
  • 迂腐,这不是正则表达式@void-pointer - 它是一种语法。 (2认同)

sev*_*vko 6

根据Python语言参考,§2.3,"标识符和关键字",有效的Python标识符定义为:

(letter|"_") (letter | digit | "_")*
Run Code Online (Sandbox Code Playgroud)

或者,在正则表达式中:

[a-zA-Z_][a-zA-Z0-9_]*
Run Code Online (Sandbox Code Playgroud)


ste*_*eha 5

使这个有趣的是标识符的第一个字符是特殊的.在第一个字符之后,数字"0"到"9"对于标识符有效,但它们不能是第一个字符.

这是一个函数,它将返回一个给定任意字符串的有效标识符.以下是它的工作原理:

首先,我们使用itr = iter(seq)在输入上获取显式迭代器.然后是第一个循环,它使用迭代器itr查看字符,直到找到标识符的有效第一个字符.然后它突破了该循环并运行第二个循环,使用相同的迭代器(我们命名itr)用于第二个循环.迭代器itr为我们保留了我们的位置; 当第二个循环运行时,第一个循环从迭代器中拉出的字符仍然消失.

def gen_valid_identifier(seq):
    # get an iterator
    itr = iter(seq)
    # pull characters until we get a legal one for first in identifer
    for ch in itr:
        if ch == '_' or ch.isalpha():
            yield ch
            break
    # pull remaining characters and yield legal ones for identifier
    for ch in itr:
        if ch == '_' or ch.isalpha() or ch.isdigit():
            yield ch

def sanitize_identifier(name):
    return ''.join(gen_valid_identifier(name))
Run Code Online (Sandbox Code Playgroud)

这是一种干净且Pythonic的方式来处理序列两种不同的方式.对于一个简单的问题,我们可以只有一个布尔变量来指示我们是否看过第一个字符:

def gen_valid_identifier(seq):
    saw_first_char = False
    for ch in seq:
        if not saw_first_char and (ch == '_' or ch.isalpha()):
            saw_first_char = True 
            yield ch
        elif saw_first_char and (ch == '_' or ch.isalpha() or ch.isdigit()):
            yield ch
Run Code Online (Sandbox Code Playgroud)

我不喜欢这个版本和第一个版本差不多.对于一个字符的特殊处理现在在整个控制流程中纠缠不清,这将比第一个版本慢,因为它必须不断检查值saw_first_char.但这是你在大多数语言中处理控制流的方式!Python的显式迭代器是一个很好的功能,我认为它使这个代码更好.

循环显式迭代器与让Python隐式获取迭代器一样快,而显式迭代器允许我们拆分处理标识符不同部分的不同规则的循环.因此,显式迭代器为我们提供了更快的代码.赢/赢.