在Python3

问题描述:

枚举奇怪的行为

我有下面的代码片段,我在python2.7.12和python3.5.2跑在Python3

f = open(file_name,'r') 
file_data= f.read() 
f.close() 
char_list = list(set(file_data)) 
c = {char:i for i,char in enumerate(char_list)} 
x = {i:char for i,char in enumerate(char_list)} 

当python2.7.12跑我得到预期的结果:

{'a': 0, ' ': 1, 'e': 2, 'i': 3, 'h': 4, '\n': 5, 'o': 6, 'r': 7, 'u': 8, 'w': 9, 'y': 10, '?': 11} 
{0: 'a', 1: ' ', 2: 'e', 3: 'i', 4: 'h', 5: '\n', 6: 'o', 7: 'r', 8: 'u', 9: 'w', 10: 'y', 11: '?'} 

在python3.5.2中,发生了一些奇怪的事情。我有时会收到效果,如:

{'h': 1, 'e': 4, 'r': 2, 'i': 3, '?': 0, '\n': 5, ' ': 6, 'u': 7, 'a': 8, 'y': 9, 'o': 10, 'w': 11} 
{0: '?', 1: 'h', 2: 'r', 3: 'i', 4: 'e', 5: '\n', 6: ' ', 7: 'u', 8: 'a', 9: 'y', 10: 'o', 11: 'w'} 

此外,在python3.5.2,但不python2.7.12,每次程序运行char_list是按不同的顺序时间。每次python2.7.12的顺序都是一样的。

在两个版本的python enumerate中都返回一个可迭代的对象。

为什么会发生这种奇怪的行为?

P.S.这也会发生当我复制char_list并将副本传递到第二个枚举而不是char_list

+1

Python字典没有排序;如果您想要易读的输出,请对其项目进行分类Python 3随机化字典顺序以帮助缓解某些攻击,并且您可以通过在环境中传递'-R'标志或设置'PYTHONHASHSEED = random'来在Python 2中启用相同的功能。 – Ryan

+0

@Ryan Well_technical_ Python 3.6的CPython解释器确实已经订购了字典。虽然这是一个实现细节,不应该依赖。 –

+0

这是否也适用于'list(set)'的返回?这似乎也是随机的。 – dylan7

枚举工作正常,但是当您将数据保存在字典中时,python不会维护顺序。默认情况下,Python字典是无序的,不能保证按照添加的顺序保持键/值对。 OrderedDict是Python的一个很好的解决方案,你可以阅读here。在CPython 3.6字典中也不会保持顺序,但这在未来不会得到保证。

如果您想要保留顺序,请考虑使用列表或元组。

我已经能够复制您的问题,并通过进行以下更改,获得预期的输出。

有两个变化。首先,编写char_list = list(set(file_data))将数据存储为一个集合,这是一个unordered data type - 也就是说,它不会保留它必须存储的订单。因此,只需删除set文本即可解决订单问题。

至于出现在结果的新行文本,只需追加.strip('\n')file_data= f.read()线,它会自动删除该文本。

进行更改,确认他们的工作,你的代码会是这个样子后:

f = open(file_name,'r') 
file_data= f.read().strip('\n') 
f.close() 
char_list = list(file_data) 
c = {char:i for i,char in enumerate(char_list)} 
x = {i:char for i,char in enumerate(char_list)} 

希望这有助于!