有没有什么方法可以转换这个for循环与列表理解?

时间:2016-11-21 09:27:00

标签: python python-2.7 for-loop list-comprehension

我要问的原因是,它包含各种数据结构,字典,列表,字符串。

bffer = ""
dict_size = 128
for character in string:
    appnd_bffer = bffer + character
    if appnd_bffer in codebook:
        bffer = appnd_bffer
    else:
        output_list.append(codebook[bffer])
        codebook[appnd_bffer] = dict_size
        dict_size += 1
        bffer = character

我是列表理解的新手,所以如果有可能我真的可以使用解释。欢呼声。

3 个答案:

答案 0 :(得分:8)

循环当前取决于能够分配给bffer。因为赋值是一个语句,而列表推导只能包含表达式,所以将它转换为列表解析需要很多难以理解的可变对象技巧。 / p>

因此,将其转换为列表解析会导致无法读取的混乱,没有任何明显的好处(删除list.append()调用的任何速度优势都将被可变对象操作所抵消。)

答案 1 :(得分:6)

只是为了让你知道为什么尝试将你的LZW压缩器循环填入列表理解是一个真的坏主意,我实际上已经开始编写一些疯狂的代码那。

它使用了一些相当狡猾的技巧,并且它不适用于Python 3,因为在Python 3中,列表理解在其自己的范围内运行;在Python 2中,列表理解在周围代码的范围内运行。这意味着我将原始缓冲区传递给list comp的技巧在Python 3中不起作用。

首先,这是包含在函数中的原始代码,其中包含一些变量名称更改,以及一些额外的附加内容,使其成为可运行的,可测试的示例。

from __future__ import print_function

def lzw_compress_Boa(data):
    dict_size = 128
    codebook = {chr(i): i for i in range(dict_size)}

    output_list = []
    oldbuff = ""
    for ch in data:
        newbuff = oldbuff + ch
        if newbuff in codebook:
            oldbuff = newbuff
        else:
            output_list.append(codebook[oldbuff])
            codebook[newbuff] = dict_size
            dict_size += 1
            oldbuff = ch
    return output_list

data = 'this data is this data'

output_list = lzw_compress_Boa(data)
print(output_list)
print(len(data), '->', len(output_list))

<强>输出

[116, 104, 105, 115, 32, 100, 97, 116, 97, 32, 130, 32, 128, 138, 133]
22 -> 15

我们实际上并不需要将代码簿的大小保存在单独的变量中。像所有Python的内置容器类型一样,dict会跟踪它的大小,我们可以使用len()函数来获取它。所以我们可以替换这两行:

codebook[newbuff] = dict_size
dict_size += 1

这一行:

codebook[newbuff] = len(codebook)

现在这里是使用列表理解的疯狂版本。记住小孩, 不要在家尝试这个! :)

def lzw_compress_crazy(data):
    dict_size = 128
    codebook = {chr(i): i for i in range(dict_size)}

    def magic(oldbuff, ch):
        newbuff = oldbuff + ch
        if newbuff in codebook:
            return [(newbuff, None)]
        else:
            codebook[newbuff] = len(codebook)
            return [(ch, codebook[oldbuff])]

    oldbuff = ""
    return [result for ch in data
        for oldbuff, result in magic(oldbuff, ch) if result]

请注意,此版本不仅比我发布的第一个版本难以阅读,而且效率也较低。正如我在开始时所说的那样,它不那么便携,而且它使用了一些完全狡猾的技巧,绝不应该用于严肃的代码。

列表理解很酷,一旦你习惯了它们,它们就可以使你的代码更简洁,这有助于提高可读性,只要你不试图在它们中做太多。在“传统”样式.append循环中,使用for的等效代码,列表组件略微 更高效,但它们不是魔术,而是使用难以理解的列表理解一个很好的清晰可读的传统for循环是 Pythonic。

答案 2 :(得分:2)

不,这不能成为列表理解,因为它包含除组成列表的表达式之外的表达式(例如dict_size += 1)。这些表达式无法进入列表理解,因为理解的唯一目的是创建该对象。可能对您有所帮助的是创建一个单独的函数,其中包含循环的单次迭代的逻辑,然后在循环中使用该函数。