我在实现内部私有枚举类时遇到了问题:" LineCode"在一个名为Parser的类中。
LineCode: Private Enum类,定义了6种通用可能代码行。我使用Enum实例化发送正则表达式模式并在构造函数__init__中编译它,然后将正则表达式匹配器保存为类变量。
Parser:解析一种编程语言,与语言无关。解析器使用LineCode来识别行并相应地继续。
问题:我无法从静态方法访问__LineCode的枚举成员。 我希望在__LineCode中有一个静态方法," matchLineCode(line)"从Parser接收一个字符串,然后按以下逻辑迭代Enum成员:
这看起来并不重要,我无法访问枚举成员来执行此操作。
尝试:我尝试使用以下方法迭代枚举:
两者都失败了,因为它无法找到__lineCode。
理想情况下: LineCode类必须是私有的,并且对于导入Parser的任何其他类都不可见。解析器必须使用LineCode类提供的静态方法来返回Enum。我愿意接受解决这个问题的任何解决方案或模仿这种行为的解决方案。
我省略了一些不相关的Parser方法来提高可读性。 代码:
class Parser:
class __LineCode(Enum):
STATEMENT = ("^\s*(.*);\s*$")
CODE_BLOCK = ("^\s*(.*)\s*\{\s*$")
CODE_BLOCK_END = ("^\s*(.*)\s*\}\s*$")
COMMENT_LINE = ("^\s*//\s*(.*)$")
COMMENT_BLOCK = ("^\s*(?:/\*\*)\s*(.*)\s*$")
COMMENT_BLOCK_END = ("^\s*(.*)\s*(?:\*/)\s*$")
BLANK_LINE = ("^\s*$")
def __init__(self, pattern):
self.__matcher = re.compile(pattern)
@property
def matches(self, line):
return self.__matcher.match(line)
@property
def lastMatch(self):
try:
return self.__matcher.groups(1)
except:
return None
@staticmethod
def matchLineCode(line):
for lineType in **???**:
if lineType.matches(line):
return lineType
return None
def __init__(self, source=None):
self.__hasNext = False
self.__instream = None
if source:
self.__instream = open(source)
def advance(self):
self.__hasNext = False
while not self.__hasNext:
line = self.__instream.readline()
if line == "": # If EOF
self.__closeFile()
return
lineCode = self.__LineCode.matchLineCode(line)
if lineCode is self.__LineCode.STATEMENT:
pass
elif lineCode is self.__LineCode.CODE_BLOCK:
pass
elif lineCode is self.__LineCode.CODE_BLOCK_END:
pass
elif lineCode is self.__LineCode.COMMENT_LINE:
pass
elif lineCode is self.__LineCode.COMMENT_BLOCK:
pass
elif lineCode is self.__LineCode.COMMENT_BLOCK:
pass
elif lineCode is self.__LineCode.BLANK_LINE:
pass
else:
pass # TODO Invalid file.
我已经用Java实现了它,我想用Python重构同样的东西:
private enum LineCode {
STATEMENT("^(.*)" + Syntax.EOL + "\\s*$"), // statement line
CODE_BLOCK("^(.*)" + Syntax.CODE_BLOCK + "\\s*$"), // code block open line
CODE_BLOCK_END("^\\s*" + Syntax.CODE_BLOCK_END + "\\s*$"), // code block close line
COMMENT_LINE("^\\s*" + Syntax.COMMENT + "(.*+)$"), // comment line
BLANK_LINE("\\s*+$"); // blank line
private final static int CONTENT_GROUP = 1;
private Pattern pattern;
private Matcher matcher;
private LineCode(String regex) {
pattern = Pattern.compile(regex);
}
boolean matches(String line) {
matcher = pattern.matcher(line);
return matcher.matches();
}
String lastMatch() {
try {
return matcher.group(CONTENT_GROUP);
} catch (IndexOutOfBoundsException e) {
return matcher.group();
}
}
static LineCode matchLineCode(String line) throws UnparsableLineException {
for (LineCode lineType : LineCode.values())
if (lineType.matches(line)) return lineType;
throw new UnparsableLineException(line);
}
感谢。
答案 0 :(得分:4)
您可以将staticmethod
更改为classmethod
,这样传递给matchLineCode
的第一个参数就是__lineCode
类,您可以迭代它
我已决定添加更详细的说明,说明使用matchLineCode
装饰器的@staticmethod
无法看到__lineCode
类的原因。首先,我建议您阅读一些关于difference between static and class methods的SO上发布的问题。主要区别在于classmethod
知道定义方法的类,而staticmethod
则不知道。这并不意味着您无法看到__lineCode
中的staticmethod
课程,只是意味着您还需要做更多的工作。
您组织代码的方式,类__lineCode
是类Parser
的类属性。在python中,方法总是公共的,没有Java中的私有或受保护的类成员。但是,类属性名称(或实例的属性名称)开头的双下划线表示名称为mangled with the class name。这意味着在类Parser
之外定义的任何函数都可以作为
__lineCode
类
Parser._Parser__lineCode
这意味着使用@staticmethod
装饰器可以通过
__lineCode
@staticmethod
def matchLineCode(line):
for lineType in Parser._Parser__lineCode:
if lineType.matches(line):
return lineType
return None
然而,它更具可读性,在我看来,使用@classmethod
装饰器来让函数知道__lineCode
类是可以理解的。