如何将普通字符串转换为原始字符串?
我现在正在开发一个工具,这个工具需要根据特定的模式来匹配文件名。为了方便起见,我打算提供两种匹配方式:一种是懒惰匹配(类似于通配符的方式),另一种是正则表达式匹配。举个例子,下面这两段代码最终会产生相同的效果:
@mylib.rule('static/*.html')
def myfunc():
pass
@mylib.rule(r'^static/([^/]+)\.html')
def myfunc():
pass
据我所知,r''
这个写法对 Python 的解析器来说是有用的,它实际上在解析后会生成一个标准的 str
实例(唯一的区别是它会保留 \
这个符号)。
有没有人知道怎么区分这两者呢?
我不想为了同样的目的提供两个不同的装饰器,或者更糟糕的是,手动解析字符串来判断它是否是正则表达式。
3 个回答
“原始字符串”这个词听起来有点让人困惑,因为它好像是一种特殊的字符串类型,其实它只是一个特殊的写法,用来告诉编译器在字符串中不要对反斜杠('\')进行任何解释。可惜的是,这个词是用来描述这种编译时的行为,但很多初学者会误以为它有一些特殊的运行时特性。
我更喜欢称它们为“原始字符串字面量”,这样可以强调它们是用一种不解释反斜杠的语法来定义字符串字面量,这就是它们被称为“原始”的原因。原始字符串字面量和普通字符串字面量都可以创建字符串(或者说是str
),而且它们生成的变量和其他字符串没有区别。用原始字符串字面量创建的字符串在各个方面都和用转义反斜杠定义的字符串是等价的。
你无法在之后判断一个字符串是否被定义为原始字符串。个人来说,我会使用一个单独的装饰器,但如果你不想这样做,可以使用命名参数,比如 @rule(glob="*.txt")
用于通配符匹配,或者 @rule(re=r".+\.txt")
用于正则表达式。
另外,如果用户想使用正则表达式,可以要求他们提供一个编译后的正则表达式对象,比如 @rule(re.compile(r".+\.txt"))
—— 这样很容易识别,因为它的类型不同。
你无法区分它们。每个原始字符串字面量都可以写成标准字符串字面量(可能需要更多的引号),反之亦然。除此之外,我肯定会给这两个装饰器起不同的名字。它们做的事情不一样,功能不同。
举个例子(CPython):
>>> a = r'^static/([^/]+)\.html'; b = '^static/([^/]+)\.html'
>>> a is b
True
所以在这个特定的例子中,原始字符串字面量和标准字符串字面量最终生成的是同一个字符串对象。