为函数生成 kwargs 映射的生成器对象

Generator object to produce kwargs mapping for function

我有一个通用的生成器函数,它将定界字符串映射到一个从定界字符串列表中产生一个 kwargs 类型的字典对象。

我想在另一个生成器函数中使用 kwargs 类型的字典作为参数。但是,我收到消息

edge_generator() argument after ** must be a mapping, not generator

这是我当前的错误代码:

def line_from_file_generator(file_name):

    with open(file_name) as text_file:
        for line in text_file:
            yield line

def map_delimited_lines_to_kwargs(lines, delimiter, kwarg_index_map):

    for line in lines:

        kwargs = {}
        args = line.strip().split(delimiter)

        for kwarg, index in kwarg_index_map.items():
            kwargs[kwarg] = args[index]

        yield kwargs


def edge_generator(source_node_name, destination_node_name, weights):

    for line in lines:
        yield Edge(source_node_name, destination_node_name, weights)


lines = line_from_file_generator('mit_map.txt')
kwarg_index_map = {'source_node_name': 0, 'destination_node_name': 1, 'weights': 2}
kwarg_collection = map_delimited_lines_to_kwargs(lines, ' ', kwarg_index_map)
edges = edge_generator(**kwargs_collection)

我现在明白为什么这是错误的(生成器是一种序列,而不是映射(可以扩展的dict))。

我可以在保留我创建的抽象的同时解决这个问题吗?密码是什么?我尝试将最后一行更改为以下内容,但它无法遍历 kwargs 生成器,并且所有边都使用相同的参数生成。

edges = edge_generator(**kwarg_collection.next())

这就是我让它工作的方式。我没有尝试在函数定义中扩展 Edge 生成器的参数,而是简单地传递了整个 kwargs 生成器,并在 Edge 生成器的主体中的 kwargs 生成器上添加了一个循环,并在创建边时扩展了参数。

def line_from_file_generator(file_name):

    with open(file_name) as text_file:
        for line in text_file:
            yield line


def kwargs_from_delimited_strings_generator(lines, delimiter, kwarg_index_map):

    for line in lines:

        kwargs = {}
        args = line.strip().split(delimiter)

        for kwarg, index in kwarg_index_map.items():
            kwargs[kwarg] = args[index]

        yield kwargs


def edge_generator(kwargs_collection):

    for kwargs in kwargs_collection:
        yield Edge(**kwargs)


lines_from_file = line_from_file_generator('mit_map.txt')
kwarg_index_map = {'source_node_name': 0, 'destination_node_name': 1,
                   'weights': 2}
kwargs_from_delimited_strings = kwargs_from_delimited_strings_generator(
                                    lines_from_file, ' ', kwarg_index_map)
edges_from_kwargs = edge_generator(kwargs_from_delimited_strings)

下面是我可能会如何修改您的程序。

请注意,我尽可能延迟使用 ** 运算符。事实上,直到我有一个具体的dict.

,我才使用它

请注意 edge_generator 迭代其参数,而不是 lines。无论如何,我不确定 lines 应该来自哪里。

请注意,生成器链已保留。在将 list() 构造函数应用于最终生成器之前,不会构建完整的边集。

def Edge(source_node_name, destination_node_name, weights):
    '''Testing version of Edge()'''
    return '{}/{}/{}'.format(source_node_name, destination_node_name, weights)

def line_from_file_generator(file_name):
    with open(file_name) as text_file:
        for line in text_file:
            yield line

def map_delimited_lines_to_kwargs(lines, delimiter, kwarg_index_map):
    for line in lines:
        kwargs = {}
        args = line.strip().split(delimiter)

        for kwarg, index in kwarg_index_map.items():
            kwargs[kwarg] = args[index]

        yield kwargs

def edge_generator(edge_attribute_dicts):
    for attribute_dict in edge_attribute_dicts:
        yield Edge(**attribute_dict)

lines = line_from_file_generator('mit_map.txt')
kwarg_index_map = {
    'source_node_name': 0,
    'destination_node_name': 1,
    'weights': 2}
kwargs_collection = map_delimited_lines_to_kwargs(lines, ' ', kwarg_index_map)
edges = edge_generator(kwargs_collection)
print(list(edges))