基于字典的开关式语句与动作

时间:2010-10-20 21:38:01

标签: python design-patterns lua

我对Python比较陌生,想知道我是在重新发明轮子还是用非pythonic方式做事 - 读错了。

我正在重写一些最初用Lua编写的解析器。有一个函数接受来自导入表及其值的字段名称,对值执行一些操作并将其以适当的键名存储在目标字典中。

在原始代码中,它通过类似开关的语句以匿名函数作为动作来解决。 Python代码如下所示:

class TransformTable:
    target_dict = {}
    ...
    def mapfield(self, fieldname, value):
        try:
            {
                'productid': self.fn_prodid,
                'name': self.fn_name,
                'description': self.fn_desc,
                ...
            }[fieldname](value)
        except KeyError:
            sys.stderr.write('Unknown key !\n')

    def fn_name(val):
        validity_check(val)
        target_dict['Product'] = val.strip().capitalize()
    ...

当然,每个“字段处理程序”函数都会执行不同的操作并存储在target_dict中的不同键中。 因为Python不支持带语句的匿名函数(或者我错过了哪些东西?),所以函数必须单独编写,这些函数的代码可读性较低且不必要复杂。

任何提示如何以更优雅和更加pythonic的方式完成此类任务都值得赞赏。

THX

大卫

2 个答案:

答案 0 :(得分:1)

如果可能,您可以根据字段名称命名您的成员函数,并执行以下操作:

getattr(self, "fn_" + fieldname)(value)

编辑:您可以使用hasattr检查函数是否存在,而不是期待KeyError。或者期望一个AttributeError。无论如何,您应该只将访问权限放在try..except内,并在外面调用,否则在其中一个字段方法中导致的KeyError可能会被误解。

答案 1 :(得分:0)

前一段时间我在我的answer中使用类似于@Matti Virkkunen'a的方法来处理标题为“switch case in python doesn't work; need another pattern”的问题。它还演示了处理未知字段的相对简单和优雅的方式。在您的示例中转换为术语,它将如下所示:

class TransformTable:
    target_dict = {}

    def productid(self, value):
        ...
    def name(self, value):
        validity_check(value)
        self.target_dict['Product'] = value.strip().capitalize()
    def description(self, value):
        ...

    def _default(self, value):
        sys.stderr.write('Unknown key!\n')

    def __call__(self, fieldname, value):
        getattr(self, fieldname, self._default)(value)

transformtable = TransformTable() # create callable instance

transformtable(fieldname, value) # use it