用于数据转换的Python设计模式

时间:2013-05-13 19:49:23

标签: python mongodb design-patterns

我发现自己做了类似的事情:

if 'id' in kwargs:
    query['_id'] = ObjectID(kwargs.pop('id'))
if 'name' in kwargs:
    query['event'] = kwargs.pop('name')
if 'keywords' in kwargs:
    keywords = kwargs.pop('keywords')
    query['keywords'] = {
        '$in': keywords
    }

忽略实施细节。这里的关键点是我正在处理两个共享相似数据并执行简单,重复和更复杂转换的数据结构。

是否有任何设计模式或其他开发人员友好的方式使这些类型的转换更容易编码?

我考虑过创建一个表和相关的函数来转换简单的属性名称,但我觉得在处理更复杂的数据转换时效果不佳。而且,从长远来看,这种方法可能无法为我节省大量工作。

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

您至少可以使用地图清除if s。当我有一大组变换时,我喜欢这样做。

transforms = {'id' : ('_id', lambda val: ObjectID(val)),
              'name' : ('event', lambda val: val),
              'keywords' : ('keywords', lambda val: val)}
for kwargs_key in kwargs.keys():
    try:
        query_key, transform = transforms[kwargs_key]
    except KeyError:
        # Default or error handling
    else:
        query[query_key] = transform(kwargs.pop(kwargs_key))

如果将它包装在类中并使transforms成为类或实例属性,则可以根据需要在运行时轻松添加或覆盖变换。

答案 1 :(得分:1)

您可以考虑将转换封装在类中:

class QueryAdapter(object):
    def __init__(self, **kwargs):
        self.kwargs = kwargs
    def __getitem__(self, item):
        try:
            method = getattr(self, item)
        except AttributeError:
            raise IndexError(item)
        else:
            return method()
    def _id(self):
        return 'ObjectID({})'.format(self.kwargs['id'])
    def event(self):
        return self.kwargs['name']
    def keywords(self):
        return {'$in': self.kwargs['keywords']}

一旦定义了QueryAdapter,其余代码就变得非常简单了:

kwargs = dict(id='abc', name='def')
query = QueryAdapter(**kwargs)

print(query['_id'])
# ObjectID(abc)
print(query['event'])
# def
print(query['keywords'])
# {'$in': 'key'}

答案 2 :(得分:0)

我现在唯一建议的是,至少只能在一个地方进行此转换。那么可能定义一个“kwargs to query”函数(最终也反过来?),它包含了一个地方的所有转换。然后在需要的地方使用该功能进行此类转换。

您可能能够创建一些更通用的方法来转换单个值,但您需要多次调用它。更不用说你必须在该通用转换方法中添加许多特殊情况。因此,只需保持完整结构的转换。