在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
答
枚举工作正常,但是当您将数据保存在字典中时,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)}
希望这有助于!
Python字典没有排序;如果您想要易读的输出,请对其项目进行分类Python 3随机化字典顺序以帮助缓解某些攻击,并且您可以通过在环境中传递'-R'标志或设置'PYTHONHASHSEED = random'来在Python 2中启用相同的功能。 – Ryan
@Ryan Well_technical_ Python 3.6的CPython解释器确实已经订购了字典。虽然这是一个实现细节,不应该依赖。 –
这是否也适用于'list(set)'的返回?这似乎也是随机的。 – dylan7