我有一个超类和一个子类,需要根据正则表达式以不同的方式处理它们的初始化。参见下面的工作示例。你知道吗
import os
import re
class Sample:
RE = r'(?P<id>\d+)'
STRICT_MATCHING = False
def __init__(self, f):
self.file = f
self.basename = os.path.basename(os.path.splitext(self.file)[0])
re_ = re.compile(self.RE)
match = re_.fullmatch if self.STRICT_MATCHING else re_.match
self.__dict__.update(match(self.basename).groupdict())
class DetailedSample(Sample):
RE = r'(?P<id>\d+)_(?P<dir>[lr])_(?P<n>\d+)'
STRICT_MATCHING = True
s1 = Sample("/asdf/2.jpg")
print(s1.id)
s2 = DetailedSample("/asdfadsf/2_l_2.jpg")
print(s2.id, s2.dir, s2.n)
此代码可以工作,但有两个缺点:
Sample
时,都会重新编译正则表达式。你知道吗Sample
中的其他类方法调用match
函数(例如,我可能希望在初始化文件Sample
之前,能够检查文件是否具有相对于RE
的有效名称)。你知道吗简单地说,我想要这样的东西:
class Sample:
RE = r'(?P<id>\d+)'
STRICT_MATCHING = False
re_ = re.compile(RE) #
match = re_.fullmatch if STRICT_MATCHING else re_.match #
def __init__(self, f):
self.file = f
self.basename = os.path.basename(os.path.splitext(self.file)[0])
self.__dict__.update(self.match(self.basename).groupdict())
@classmethod
def valid(cls, f):
basename, ext = os.path.splitext(os.path.basename(f))
return cls.match(basename) and ext.lower() in ('.jpg', '.jpeg', '.png')
class DetailedSample(Sample):
RE = r'(?P<id>\d+)_(?P<dir>[lr])_(?P<n>\d+)'
STRICT_MATCHING = True
然而,这显然在子类中不起作用,因为在重新定义子类中的RE
和STRICT_MATCHING
之后,用#
标记的两行不会执行。你知道吗
是否有一种方法可以:
STRICT_MATCHING
参数?你知道吗
您可以缓存/记忆wiki.python.org中提到的已编译正则表达式,如果实例属性:
输出:
。。。正如你所看到的。表达式只编译了两次。你知道吗
你可以通过装饰类来做到这一点。你知道吗
这个装饰器检查
STRICT_MATCHING
属性并相应地设置match
属性。你知道吗使用元类可以获得相同的效果:
但在我看来,使用类装饰器(或chepner的答案中描述的
__init_subclass__
)更具可读性和可理解性。你知道吗您可以使用
__init_subclass__
来确保每个子类执行适当的工作。这将在公共基类继承的私有基类中定义。你知道吗除非以后需要直接访问已编译的正则表达式,
_re
可以是_BaseSample.__init_subclass__
的局部变量,而不是每个类的类属性。你知道吗请注意,
__init_subclass__
还可以接受其他关键字参数,这些参数作为关键字参数提供给class
语句本身。我不认为这样做有什么特别的好处;这只是您想要为设置RE
和STRICT_MATCHING
提供什么接口的问题。详见Customizing Class Creation。你知道吗相关问题 更多 >
编程相关推荐