使用全局变量或传入参数来映射函数是否更好?

时间:2016-04-15 19:41:47

标签: python dictionary functional-programming arguments

我正在使用pyspark来处理服务器日志,我对函数式编程概念很陌生。我有一个查找表,我在我的函数中使用它来从众多选项中进行选择:

user_agent_vals = {
        'CanvasAPI': 'api',
        'candroid': 'mobile_app_android',
        'iCanvas': 'mobile_app_ios',
        'CanvasKit': 'mobile_app_ios',
        'Windows NT': 'desktop',
        'MacBook': 'desktop',
        'iPhone': 'mobile',
        'iPod Touch': 'mobile',
        'iPad': 'mobile',
        'iOS': 'mobile',
        'CrOS': 'desktop',
        'Android': 'mobile',
        'Linux': 'desktop',
        'Mac OS': 'desktop',
        'Macintosh': 'desktop'
    }

def parse_requests(line):
    """
    Expects an input list, which is then mapped to the correct fieldnames in
    a dict.

    :param line: A list of values.
    :return: A list containing the values for writing to a file.
    """
    values = dict(zip(requests_fieldnames, line))
    print(values)
    values['request_timestamp'] = values['request_timestamp'].split('-')[1]
    found = False
    for key, value in user_agent_vals.items():
        if key in values['user_agent']:
            found = True
            values['user_agent'] = value
    if not found:
        values['user_agent'] = 'other_unknown'
    return [
        values['user_id'],
        values['context_id'],
        values['request_timestamp'],
        values['user_agent']
    ]

每次调用函数时我都不想重新定义字典(这将是数百万次),但是只是使用Python的LEGB查找让它找到字典中的字典似乎有些“脏”。模块命名空间我应该将一个参数(如果是这样,如何?)传递给调用parse_requests的map函数,或者处理此问题的最佳实践方法是什么?

供参考,这是我的地图电话:

parsed_data = course_data.map(parse_requests)

2 个答案:

答案 0 :(得分:1)

对于这样的全局"常数"使用全部大写是一种惯例:

USER_AGENT_VALS

例如,pylint的默认设置仅允许模块级别的变量(函数和类除外)的所有大写名称。

或者,您可以提供user_agent_vals作为第二个参数:

def parse_requests(line, user_agent_vals):

致电:

parse_requests(line, user_agent_vals)

你可以"冻结" functools.partial()函数的参数:

from functools import partial

parse_requests_for_map = partial(parse_requests, user_agent_vals=user_agent_vals)

现在,您可以将其与map

一起使用
parsed_data = course_data.map(parse_requests_for_map)

答案 1 :(得分:1)

将您需要的所有东西放在一个对象中,并使该对象成为一个"可调用的" (通过定义一些def __call__(self, arg):方法),并将对象作为要使用的地图的函数传递。

很好的例子here(对于多处理的地图,但该技术更普遍适用)。