理解:参考组件

dou*_*oug 8 python interpreter list-comprehension internals

总而言之:我需要编写一个列表理解,其中我引用列表理解正在创建的列表.

这可能不是你每天都需要做的事情,但我认为这也不常见.

也许这里没有答案 - 但是,请不要告诉我,我应该使用for循环.这可能是正确的,但没有用.原因是问题域:这行代码是ETL模块的一部分,因此性能是相关的,因此需要避免创建临时容器 - 因此我希望在L/C中编写此步骤.如果for循环在这里对我有用,我只想编码一个.

无论如何,我无法写出这个特定的列表理解.原因:我需要写的表达式有这样的形式:

[ some_function(s) for s in raw_data if s not in this_list ]
Run Code Online (Sandbox Code Playgroud)

在该伪代码中,"this_list"指的是通过评估该列表理解而创建的列表.这就是为什么我被卡住了 - 因为this_list在我的列表理解被评估之前没有构建,并且因为这个列表还没有在我需要引用它的时候构建,所以我不知道如何引用它.

我到目前为止所考虑的(可能是基于一个或多个错误假设,但我不确切知道在哪里):

  • 是不是python解释器必须给这个列表在建设中一个名字?我认同

  • 临时名称可能来自用于构建我的列表的一些绑定方法('sum'?)

  • 但即使我找到了绑定方法的麻烦,并假设它确实是python解释器在构建时引用列表时使用的临时名称,我很确定你不能引用绑定方法直; 我不知道这样一个明确的规则,但那些方法(至少我实际看过的几个)都不是有效的python语法.我猜是为什么我们不将它们写入代码中的原因之一.

所以这就是我所谓推理的链条,这让我得出结论,或者至少猜测,我把自己编成了一个角落.我仍然认为我应该先与社区核实这一点,然后再转向另一个方向.

mar*_*eau 3

曾经有一种方法可以使用未记录的事实来做到这一点:在构建列表时,其值存储在名为 的局部变量中_[1].__self__。然而,它在 Python 2.7 中停止工作(也许更早,我没有密切关注)。

如果您首先设置外部数据结构,则可以在单个列表理解中执行您想要的操作。由于您所有的伪代码似乎都是在this_list检查它以查看每个伪代码是否s已经在其中 - 即成员资格测试 - 我已将其更改为set命名seen作为优化(检查 a 中的成员资格list可能非常慢如果列表很大)。这就是我的意思:

raw_data = [c for c in 'abcdaebfc']

seen = set()
def some_function(s):
    seen.add(s)
    return s

print [ some_function(s) for s in raw_data if s not in seen ]
# ['a', 'b', 'c', 'd', 'e', 'f']
Run Code Online (Sandbox Code Playgroud)

如果您无权访问some_function,您可以在自己的包装函数中调用它,该函数seen在返回之前将其返回值添加到集合中。

即使它不是列表理解,我也会将整个事情封装在一个函数中以使重用更容易:

def some_function(s):
    # do something with or to 's'...
    return s

def add_unique(function, data):
    result = []
    seen = set(result) # init to empty set
    for s in data:
        if s not in seen:
            t = function(s)
            result.append(t)
            seen.add(t)
    return result

print add_unique(some_function, raw_data)
# ['a', 'b', 'c', 'd', 'e', 'f']
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,我都觉得奇怪的是,在您想要引用的伪代码中构建的列表不是由值的子集组成,而是由调用每个值raw_data的结果(即转换后的数据)组成。some_function自然会让人想知道是什么some_function使得它的返回值可能与现有raw_data项目的值匹配。