如何将常量与函数完全关联?

时间:2013-05-15 00:19:16

标签: python

我有一系列函数应用于数据集中的每个记录,以生成我存储在字典中的新字段(记录 - “文档” - 使用MongoDB存储)。我把它们全部打破了,因为它们基本上是不相关的,并将它们作为一个列表传递给一个函数,将它们重新组合在一起,迭代每个记录的每个操作并添加结果。

让我感到烦恼的是我是如何以一种看起来相当不优雅的方式去做的;半复制的名字等。

def _midline_length(blob):
    '''Generate a midline sequence for *blob*'''
    return 42
midline_length = {
        'func':  _midline_length,
        'key': 'calc_seq_midlen'} #: Midline sequence key/function pair.

很多这些......

do_calcs = [midline_length, ] # all the functions ...

然后调用如:

for record in mongo_collection.find():
    for calc in do_calcs:
        record[calc['key']] = calc['func'](record) # add new data to record
    # update record in DB

像这样拆分键可以更容易地删除数据库中的所有计算字段(在完成所有设置之后毫无意义,但在开发代码和方法时,它很方便)。

我想过可能会使用类,但它看起来更像是 ab

class midline_length(object):
    key = 'calc_seq_midlen'
    @staticmethod
    def __call__(blob):
        return 42

然后我可以创建一个实例列表(do_calcs = [midline_length(), ...]),并通过调用每个事件或拉出它的key成员。或者,似乎我可以随意添加成员到函数def myfunc():然后myfunc.key = 'mykey' ......这看起来更糟糕。更好的想法?

2 个答案:

答案 0 :(得分:3)

您可能希望为此目的使用装饰器。

import collections
RecordFunc = collections.namedtuple('RecordFunc', 'key func')

def record(key):
    def wrapped(func):
        return RecordFunc(key, func)
    return wrapped

@record('midline_length')
def midline_length(blob):
    return 42

现在,midline_length实际上不是一个函数,但它是一个RecordFunc对象。

>>> midline_length
RecordFunc(key='midline_length', func=<function midline_length at 0x24b92f8>)

它具有func属性,这是原始函数和key属性。

如果将它们添加到同一个字典中,您可以在装饰器中执行:

RECORD_PARSERS = {}

def record(key):
    def wrapped(func):
        RECORD_PARSERS[key] = func
        return func
    return wrapped

@record('midline_length')
def midline_length(blob):
    return 42

答案 1 :(得分:0)

这对装饰师来说是一个完美的工作。类似的东西:

_CALC_FUNCTIONS = {}
def calcfunc(orig_func):
    global _CALC_FUNCTIONS
    # format the db name from the function name.
    key = 'calc_%s' % orig_func.__name__
    # note we're using a set so these will
    _CALC_FUNCTIONS[key] = orig_func
    return orig_func

@calcfunc
def _midline_length(blob):
    return 42

print _CALC_FUNCTIONS
# prints {'calc__midline_length': <function _midline_length at 0x035F7BF0>}

# then your document update is as follows
for record in mongo_collection.find():
    for key, func in _CALC_FUNCTIONS.iteritems():
        record[key] = func(record)
    # update in db

请注意,您也可以像Dietrich指出的那样将属性存储在函数对象本身上,但您可能仍需要保留全局结构以保留函数列表。