关于列表:来自字符串的Python名称变量

Python name variable from string

本问题已经有最佳答案,请猛点这里访问。

是否可以基于字符串的值创建变量名?

我有一个脚本,它将读取一个文件中的信息块,并将它们存储在字典中。然后将每个块的字典附加到"master"字典中。文件中信息块的数量会有所不同,并使用"完成"一词来指示块的结尾。

我想这样做:

1
2
3
4
5
6
7
8
master={}
block=0
for lines in file:
  if line !="done":
    $block.append(line)
  elif line =="done":
    master['$block'].append($block)
    block = block + 1

如果文件包含这样的内容:

1
2
3
4
5
6
7
eggs
done
bacon
done
ham
cheese
done

结果将是一本字典,有3个列表:

1
master = {'0': ["eggs"], '1': ["bacon"], '2': ["ham","cheese"]}

这是怎么做到的?


我真的建议你用列表来代替。有没有什么具体的点,为什么你需要数组式的听写?

如果可以使用数组,则可以使用以下命令:

1
2
with open("yourFile") as fd:
    arr = [x.strip().split() for x in fd.read().split("done")][:-1]

输出:

1
[['eggs'], ['bacon'], ['ham', 'cheese']]

如果需要数字字符串索引,可以使用以下方法:

1
2
3
with open("yourFile") as fd:
    l = [x.strip().split() for x in fd.read().split("done")][:-1]
    print dict(zip(map(str,range(len(l))),l))


你似乎误解了字典的工作原理。他们拿的钥匙是物体,所以这里不需要魔法。

但是,我们可以使用collections.defaultdict根据需要制作子列表,从而使您的代码更好。

1
2
3
4
5
6
7
8
9
from collections import defaultdict

master = defaultdict(list)
block = 0
for line in file:
    if line =="done":
        block += 1
    else:
        master[block].append(line)

不过,我建议,如果你想要连续的、有编号的索引,字典是不必要的——这就是列表的目的。在这种情况下,我建议您遵循Thrustmaster的第一个建议,或者作为一个替代方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
from itertools import takewhile

def repeat_while(predicate, action):
    while True:
        current = action()
        if not predicate(current):
            break
        else:
            yield current

with open("test") as file:
    action = lambda: list(takewhile(lambda line: not line =="done", (line.strip() for line in file)))
    print(list(repeat_while(lambda x: x, action)))


我认为"完成"的分裂注定要失败。考虑以下列表:

1
2
3
4
5
6
7
eggs
done
bacon
done
rare steak
well done stake
done

从Thrustmaster偷东西(我偷东西给了+1),我建议:

1
2
3
4
>>> dict(enumerate(l.split() for l in open(file).read().split('
done
'
) if l))
{0: ['eggs'], 1: ['bacon'], 2: ['ham', 'cheese']}

我知道这需要一个尾随的""。如果有问题,可以使用"open(file.read()+''"或甚至"+'行'",如果最后完成是可选的。


这是您的代码,用于并列:

1
2
3
4
5
6
7
8
master={}
block=0
for lines in file:
  if line !="done":
    $block.append(line)
  elif line =="done":
    master['$block'].append($block)
    block = block + 1

正如ThrustMaster在文章中提到的,在这里使用嵌套列表更有意义。以下是您将如何做到这一点的方法;我在结构上尽可能少地更改了您的原始代码:

1
2
3
4
5
6
master=[[]] # Start with a list containing only a single list
for line in file: # Note the typo in your code: you wrote"for lines in file"
  if line !="done":
    master[-1].append(line) # Index -1 is the last element of your list
  else: # Since it's not not"done", it must in fact be"done"
    master.append([])

这里唯一的一点是,在您的EDOCX1[1]列表的末尾会有一个额外的列表,因此您应该在EDOCX1[2]中添加一行,以检测最后一个空子列表:

1
del master[-1]

使用setattr或globals()。请参阅如何在当前模块上调用setattr()?