简体   繁体   English

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

[英]How can I cleanly associate a constant with a function?

I have a series of functions that I apply to each record in a dataset to generate a new field I store in a dictionary (the records—"documents"—are stored using MongoDB). 我有一系列函数,我应用于数据集中的每个记录,以生成我存储在字典中的新字段(记录 - “文档” - 使用MongoDB存储)。 I broke them all up as they are basically unrelated, and tie them back together by passing them as a list to a function that iterates through each operation for each record and adds on the results. 我将它们全部拆开,因为它们基本上是不相关的,并将它们作为一个列表传递给一个函数,将它们重新组合在一起,迭代每个记录的每个操作并添加结果。

What irks me is how I'm going about it in what seems like a fairly inelegant manner; 让我感到烦恼的是我是如何以一种看起来相当不优雅的方式去做的; semi-duplicating names among other things. 半复制名称等。

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.

Lots of these... 很多这些......

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

Then called like: 然后调用如:

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

Splitting up the keys like this makes it easier to remove all the calculated fields in the database (pointless after everything is set, but while developing the code and methodology it's handy). 像这样拆分键可以更容易地删除数据库中的所有计算字段(在设置完所有内容后毫无意义,但在开发代码和方法时,它很方便)。

I had the thought to maybe use classes, but it seems more like an ab use: 我曾想过可能会使用类,但它似乎更像是ab使用:

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

I could then make a list of instances ( do_calcs = [midline_length(), ...] ) and run through that calling each thing or pulling out it's key member. 然后我可以创建一个实例列表( do_calcs = [midline_length(), ...] )并运行调用每个东西或拉出它的key成员。 Alternatively, it seems like I can arbitrarily add members to functions, def myfunc(): then myfunc.key = 'mykey' ...that seems even worse. 或者,似乎我可以任意添加成员到函数, def myfunc():然后myfunc.key = 'mykey' ......这看起来更糟糕。 Better ideas? 好主意?

You might want to use decorators for this purpose. 您可能希望使用装饰器来实现此目的。

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

Now, midline_length is not actually a function, but it is a RecordFunc object. 现在, midline_length实际上不是一个函数,但它是一个RecordFunc对象。

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

It has a func attribute, which is the original function, and a key attribute. 它有一个func属性,它是原始函数和一个key属性。

If they get added to the same dictionary, you can do it in the decorator: 如果它们被添加到同一个字典中,您可以在装饰器中执行:

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

This is a perfect job for a decorator. 这对于装饰者来说是一个完美的工作。 Something like: 就像是:

_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

Note that you could also store the attributes on the function object itself like Dietrich pointed out but you'll probably still need to keep a global structure to keep the list of functions. 请注意,您也可以像Dietrich指出的那样将属性存储在函数对象本身上,但您可能仍需要保留全局结构来保留函数列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM