我有一系列函数应用于数据集中的每个记录,以生成我存储在字典中的新字段(记录 - “文档” - 使用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'
......这看起来更糟糕。更好的想法?
答案 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指出的那样将属性存储在函数对象本身上,但您可能仍需要保留全局结构以保留函数列表。