只是为了让你知道为什么它是一个确实不好主意尝试和填充你的LZW压缩器的循环列表理解,我已经写了一些疯狂的代码,这样做。
它使用了一些比较狡猾的技巧,它不适用于Python 3,因为在Python 3中,列表理解运行在它自己的范围内;在Python 2中,列表理解运行在周围代码的范围内。这意味着我将原始缓冲区传递到列表组件中的技巧在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的内置容器类型一样,字典跟踪其大小,我们可以使用len()
函数来获取它。这条线
codebook[newbuff] = dict_size
dict_size += 1
:所以我们可以替换这些2线
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]
请注意,这个版本不仅比我发布的第一个版本更难读取,它的效率也不高。正如我在开始时所说的那样,它的便携性较差,而且它使用了一些永远不会用于严肃代码的完全狡猾的技巧。
列表理解是冷静,一旦你已经习惯了他们,他们可以使你的代码更简洁,它可以帮助可读性,只要你不要试图做太多在其中。列表比较是略比“传统”风格for
循环使用.append
等效代码效率更高,但它们不是魔术,并使用难以理解的列表理解,而不是AA漂亮清晰可读传统for
环路不 Python的。
为什么需要这个被转换成一个列表理解?这真的会伤害可读性。 –
你为什么想要?如果由某种恶魔巫术,它是可以堵塞所有到一个列表理解,这将是完全不可读。 –
'[do_everything_youre_doing_in_the_loop(字符),用于字符串的字符]'...?这是太多的代码内联成一个修真... – deceze