假设我有一个派生自str
的自定义类,它实现/覆盖了一些方法:
class mystr(str):
# just an example for a custom method:
def something(self):
return "anything"
现在我必须通过在构造函数中传递一个字符串来手动创建mystr
的实例:
ms1 = mystr("my string")
s = "another string"
ms2 = mystr(s)
这不是太糟糕,但它导致使用类似于b'bytes string'
或r'raw string'
或u'unicode string'
的自定义字符串前缀会很酷。
在Python中以某种方式可以创建/注册像m
这样的自定义字符串文字前缀,以便文字m'my string'
生成mystr
的新实例吗?
或者这些前缀是否已经硬编码到Python解释器中?
答案 0 :(得分:13)
这些前缀在解释器中是硬编码的,你不能注册更多的前缀。
可以做什么,是使用自定义源编解码器对Python文件进行预处理。这是一个相当简洁的黑客,需要您注册自定义编解码器,并理解和应用源代码转换。
Python允许您在顶部使用特殊注释指定源代码的编码:
# coding: utf-8
会告诉Python使用UTF-8编码的源代码,并在解析之前相应地解码文件。 Python在codecs
模块注册表中查找编解码器。 您可以注册自己的编解码器。
pyxl project使用这个技巧从Python文件中解析HTML语法,用实际的Python语法替换它们来构建HTML,所有这些都在“解码”步骤中完成。请参阅该项目中的codec
package,其中register
module注册了custom codec
search function,在Python实际解析和编译之前,它会转换源代码。在site-packages
目录中安装了custom .pth
file,以便在Python启动时加载此注册步骤。另一个用于解析Ruby样式字符串格式的项目是interpy
。
然后你需要做的就是构建一个这样的编解码器,它将解析一个Python源文件(用它标记它,可能用tokenize
module)并用你的自定义前缀替换字符串文字{{1}调用。您要解析的任何文件都标有mystr(<string literal>)
。
我会将这部分作为练习留给读者。祝你好运!
注意,然后将此转换的结果编译为字节码,该字节码被缓存;您的转换只需要为每个源代码修订版运行一次,使用您的编解码器的所有其他模块导入都将加载缓存的字节码。
答案 1 :(得分:2)
可以使用运算符重载将str
隐式转换为自定义类
class MyString(str):
def __or__( self, a ):
return MyString(self + a)
m = MyString('')
print( m, type(m) )
#('', <class 'MyString'>)
print m|'a', type(m|'a')
#('a', <class 'MyString'>)
这避免了使用括号有效地模拟带有一个额外字符的字符串前缀-我选择将其作为|
,但也可以是&
或其他二进制比较运算符。
答案 2 :(得分:1)
尽管上述解决方法很不错,但它们可能很危险。黑客Python确实不是一个好主意。虽然否则您实际上无法做一个前缀, 您可以执行以下操作:
class MyString(str):
def something(self):
return MyString("anything")
m = MyString
# The you can do:
m("hi")
# Rather than:
# m"hi"
这可能是您可以找到的最佳安全解决方案。 输入两个括号实际上并不是那么多,并且可以减少代码阅读者的困惑。