Python:私有内部枚举中的静态方法class
Python: Static method inside private inner Enum class
我在实现名为 class 的内部私有枚举 class 时遇到问题: "LineCode" 在 class 命名的解析器中。
LineCode: Private Enum class 定义了 6 种一般可能的代码行。我使用枚举实例化来发送正则表达式模式并在构造函数 __init__ 中编译它,然后将正则表达式匹配器作为 class 变量保存。
Parser: 解析一种编程语言,与什么语言无关。解析器正在使用 LineCode 来识别行并进行相应处理。
问题: 我无法从静态方法访问 __LineCode 的枚举成员。
我希望在 __LineCode、"matchLineCode(line)" 中有一个静态方法,它从解析器接收一个字符串,然后按以下逻辑遍历 Enum 成员:
- 如果找到匹配项:Return 枚举
- 如果没有更多枚举剩余:Return None
这看起来并不简单,我无法访问枚举成员来执行此操作。
尝试: 我尝试使用以下方法遍历枚举:
- __LineCode.__members__.values()
- Parser.__lineCode.__members__.values()
都失败了,因为它找不到 __lineCode。
理想情况下: LineCode class 必须是私有的,并且对导入解析器的任何其他 class 不可见。解析器必须使用 LineCode class 提供给 return 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);
}
谢谢。
您可以将 staticmethod
更改为 classmethod
,这样传递给 matchLineCode
的第一个参数将是 __lineCode
class,您将能够迭代它
编辑
我决定添加更详细的解释,说明为什么使用 @staticmethod
装饰器的 matchLineCode
无法看到 __lineCode
class。首先,我建议您阅读 SO 上发布的一些关于 difference between static and class methods 的问题。主要区别在于 classmethod
知道定义方法的 Class,而 staticmethod
不知道。这并不意味着您无法从 staticmethod
中看到 __lineCode
class,它只是意味着您将需要做更多的工作才能做到这一点。
您组织代码的方式,class __lineCode
是 class Parser
的 class 属性。在 python 中,方法总是 public,没有私有或受保护的 class 成员,如在 Java 中。但是,class 属性名称(或实例的属性名称)开头的双下划线表示该名称将为 mangled with the class name。这意味着在 class Parser
之外定义的任何函数都可以访问 __lineCode
class 作为
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
class.
我在实现名为 class 的内部私有枚举 class 时遇到问题: "LineCode" 在 class 命名的解析器中。
LineCode: Private Enum class 定义了 6 种一般可能的代码行。我使用枚举实例化来发送正则表达式模式并在构造函数 __init__ 中编译它,然后将正则表达式匹配器作为 class 变量保存。
Parser: 解析一种编程语言,与什么语言无关。解析器正在使用 LineCode 来识别行并进行相应处理。
问题: 我无法从静态方法访问 __LineCode 的枚举成员。 我希望在 __LineCode、"matchLineCode(line)" 中有一个静态方法,它从解析器接收一个字符串,然后按以下逻辑遍历 Enum 成员:
- 如果找到匹配项:Return 枚举
- 如果没有更多枚举剩余:Return None
这看起来并不简单,我无法访问枚举成员来执行此操作。
尝试: 我尝试使用以下方法遍历枚举:
- __LineCode.__members__.values()
- Parser.__lineCode.__members__.values()
都失败了,因为它找不到 __lineCode。
理想情况下: LineCode class 必须是私有的,并且对导入解析器的任何其他 class 不可见。解析器必须使用 LineCode class 提供给 return 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);
}
谢谢。
您可以将 staticmethod
更改为 classmethod
,这样传递给 matchLineCode
的第一个参数将是 __lineCode
class,您将能够迭代它
编辑
我决定添加更详细的解释,说明为什么使用 @staticmethod
装饰器的 matchLineCode
无法看到 __lineCode
class。首先,我建议您阅读 SO 上发布的一些关于 difference between static and class methods 的问题。主要区别在于 classmethod
知道定义方法的 Class,而 staticmethod
不知道。这并不意味着您无法从 staticmethod
中看到 __lineCode
class,它只是意味着您将需要做更多的工作才能做到这一点。
您组织代码的方式,class __lineCode
是 class Parser
的 class 属性。在 python 中,方法总是 public,没有私有或受保护的 class 成员,如在 Java 中。但是,class 属性名称(或实例的属性名称)开头的双下划线表示该名称将为 mangled with the class name。这意味着在 class Parser
之外定义的任何函数都可以访问 __lineCode
class 作为
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
class.