我有一个父类(super class)和一个子类,它们需要基于正则表达式以不同方式处理它们的初始化。请参阅下面的工作示例。
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
都会重新编译正则表达式被初始化。 match
Sample
中的其他类方法不能调用函数(例如,我可能希望能够检查一个文件是否有一个有效的名称 - 相对于 RE
- 在从它初始化 Sample
之前)。 简单地说,我想要这样的东西:
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
子类中的参数? 最佳答案
您可以使用 __init_subclass__
确保每个子类都做适当的工作。这将在您的公共(public)基类继承的私有(private)基类中定义。
import os
import re
class _BaseSample:
RE = r'(?P<id>\d+)'
STRICT_MATCHING = False
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls._re = re.compile(cls.RE)
cls.match = cls._re.fullmatch if cls.STRICT_MATCHING else cls._re.match
class Sample(_BaseSample):
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())
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)
除非您以后需要直接访问已编译的正则表达式,否则
_re
可以是 _BaseSample.__init_subclass__
的局部变量而不是每个类的类属性。请注意
__init_subclass__
也可以接受额外的关键字参数,作为关键字参数提供给 class
声明本身。我不认为这样做有什么特别的好处。这只是你想提供什么接口(interface)来设置RE
的问题。和 STRICT_MATCHING
.见 Customizing Class Creation详情。
关于Python - 覆盖类变量的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58995817/