Python 3和Python 2中XOR函数的区别是什么?

3

在IDLE、Python 3.6.5和Python 2.7.15中,我遇到了一个与XOR相关的奇怪问题。在Python 2.7中,我得到了正确的答案,而在Python 3.6中,却得到了垃圾结果。Python 3.6和2.7对于一个简单的XOR操作的结果并不一致。这不是IDLE的问题,因为在cygwin中的表现也是相同的。

>>> ciphertext

'466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83'

Python 2.7

>>> ciphertext.decode('hex')
'Fm\x06\xec\xe9\x98\xb7\xa2\xfb\x1dFO\xed,\xedvA\xdd\xaa<\xc3\x1c\x99A\xcf\x11\n\xbb\xf4\t\xed9Y\x80\x05\xb39\x9c\xcf\xaf\xb6\x1d\x03\x15\xfc\xa0\xa3\x14\xbe\x13\x8a\x9f2P;\xed\xac\x80g\xf0:\xdb\xf3W\\;\x8e\xdc\x9b\xa7\xf57S\x05A\xab\x0f\x9f<\xd0O\xf5\rf\xf1\xd5Y\xbaR\x0e\x89\xa2\xcb*\x83'
>>> for x, y in zip(ciphertext.decode('hex'), ' '*10):
    print "ord(x): " + chr(ord(x))
    print "ord(y): " + chr(ord(y))
    print(chr(ord(x) ^ ord(y)))


ord(x): F
ord(y):  
f
ord(x): m
ord(y):  
M
ord(x): 
ord(y): 
&
ord(x): ì
ord(y):  
Ì
ord(x): é
ord(y):  
É
ord(x): ˜
ord(y):  
¸
ord(x): ·
ord(y):  
—
ord(x): ¢
ord(y):  
‚
ord(x): û
ord(y):  
Û
ord(x): 
ord(y):  
=

Python 3.6

 >>> bytes.fromhex(ciphertext)

   b'Fm\x06\xec\xe9\x98\xb7\xa2\xfb\x1dFO\xed,\xedvA\xdd\xaa<\xc3\x1c\x99A\xcf\x11\n\xbb\xf4\t\xed9Y\x80\x05\xb39\x9c\xcf\xaf\xb6\x1d\x03\x15\xfc\xa0\xa3\x14\xbe\x13\x8a\x9f2P;\xed\xac\x80g\xf0:\xdb\xf3W\\;\x8e\xdc\x9b\xa7\xf57S\x05A\xab\x0f\x9f<\xd0O\xf5\rf\xf1\xd5Y\xbaR\x0e\x89\xa2\xcb*\x83'
>>> for x, y in zip(bytes.fromhex(ciphertext), ' '*10):
    print("x: ", chr(x))
    print("ord(y): ", chr(ord(y)))
    print(chr(x^ord(y)))


x:  F
ord(y):   
f
x:  m
ord(y):   
M
x:  
ord(y):   
&
x:  ì
ord(y):   
Ì
x:  é
ord(y):   
É
x:  
ord(y):   
¸
x:  ·
ord(y):   
<- different value
x:  ¢
ord(y):   
<- different value
x:  û
ord(y):   
Û
x:  
ord(y):   
=

In a cygwin window I get the following:
$ ./python2_test.py
Fm▒阷▒▒FO▒,▒vAݪ<▒▒A▒
f▒▒Y▒R▒▒▒*▒▒▒9▒ϯ▒▒▒▒▒▒▒2P;▒g▒:▒▒W\;▒ܛ▒▒7SA▒▒<▒O▒
ord(x): F
ord(y):
f
ord(x): m
ord(y):
M
ord(x):
ord(y):
&
ord(x): ▒
ord(y):
▒
ord(x): ▒
ord(y):
▒
ord(x): ▒
ord(y):
▒
ord(x): ▒
ord(y):
▒
ord(x): ▒
ord(y):
▒
ord(x): ▒
ord(y):
▒
ord(x):
ord(y):
=
$ ./python3_test.py
b'Fm\x06\xec\xe9\x98\xb7\xa2\xfb\x1dFO\xed,\xedvA\xdd\xaa<\xc3\x1c\x99A\xcf\x11\n\xbb\xf4\t\xed9Y\x80\x05\xb39\x9c\xcf\xaf\xb6\x1d\x03\x15\xfc\xa0\xa3\x14\xbe\x13\x8a\x9f2P;\xed\xac\x80g\xf0:\xdb\xf3W\\;\x8e\xdc\x9b\xa7\xf57S\x05A\xab\x0f\x9f<\xd0O\xf5\rf\xf1\xd5Y\xbaR\x0e\x89\xa2\xcb*\x83'
x:  F
ord(y):
f
x:  m
ord(y):
M
x:
ord(y):
&
x:  ì
ord(y):
Ì
x:  é
ord(y):
É
x:  
ord(y):
¸
x:  ·
ord(y):
<- missing
x:  ¢
ord(y):
<- missing
x:  û
ord(y):
Û
x:
ord(y):
=

任何帮助解决这个问题,将不胜感激。 谢谢。
1个回答

1
我认为你看到的是编码问题。如果您尝试打印数字而不是字符来重现步骤,您将看不到任何区别。以下是这些脚本:
Python2:
ciphertext = '466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83'

out1 = []
out2 = []
out3 = []
for x, y in zip(ciphertext.decode('hex'), ' '*10):
    out1.append(hex(ord(x)))
    out2.append(hex(ord(y)))
    out3.append(hex(ord(x) ^ ord(y)))
print out1
print out2
print out3

Python 3:

ciphertext = '466d06ece998b7a2fb1d464fed2ced7641ddaa3cc31c9941cf110abbf409ed39598005b3399ccfafb61d0315fca0a314be138a9f32503bedac8067f03adbf3575c3b8edc9ba7f537530541ab0f9f3cd04ff50d66f1d559ba520e89a2cb2a83'
out1 = []
out2 = []
out3 = []
for x, y in zip(bytes.fromhex(ciphertext), ' '*10):
    out1.append(x)
    out2.append(ord(y))
    out3.append(x ^ ord(y))
print(out1)
print(out2)
print(out3)

如果您同时执行它们,您会发现输出结果是相同的。

您可以直接在ideone上查看,python2python3

编辑:我提供的脚本的执行,稍作修改以显示十六进制而不是原始数字,给我输出:

Python2:

['0x46', '0x6d', '0x6', '0xec', '0xe9', '0x98', '0xb7', '0xa2', '0xfb', '0x1d']
['0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20']
['0x66', '0x4d', '0x26', '0xcc', '0xc9', '0xb8', '0x97', '0x82', '0xdb', '0x3d']

Python3:

['0x46', '0x6d', '0x6', '0xec', '0xe9', '0x98', '0xb7', '0xa2', '0xfb', '0x1d']
['0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20', '0x20']
['0x66', '0x4d', '0x26', '0xcc', '0xc9', '0xb8', '0x97', '0x82', '0xdb', '0x3d']

使用您提供的相同输入数据,我有一个不同的输入,但我的Python2和Python3之间的输出数据是连贯的。


bracco23 - 感谢您的及时回复,但是我在我的程序中发现了Python 3和Python 2的异或运算的差异。 - Jam One
bracco23 - 感谢您的及时回复,但是我在我的程序中发现了Python 3和Python 2 XOR之间的差异。例如,在Python 2中,我获得了以下结果:[66、c9、cd、29、19、19、80、12、d0、fc、8b、bf、f0、9a],这是正确的,而在Python 3中,使用相同数据进行XOR运算时,我得到了[66、c389、c38d、29、19、19、c280、12、c390、c3bc、c28b、c2bf、c3b0、c29a],这会导致错误。我不知道像'c389'这样的十六进制值会从我的数据哪里来。 - Jam One
@JamOne 我已经编辑了答案并给出了我的输出,这在Python2和Python3之间是相同的。如果可以的话,请编辑您的问题并使用像ideone这样的服务来共享可执行的[mcve](不要忘记在问题本身中包含代码)。 - bracco23
再次感谢您的耐心等待。我已经使用了 ideone 服务。 - Jam One
再次感谢您的耐心等待。我已经使用了ideone服务。对于Python 2.6(https://ideone.com/eIRNh8)和Python 3.4(https://ideone.com/0RLKUN),基本上是完全相同的代码,只是在Python 2和3之间有一些微小的差异,但我得到了非常不同的答案。对于2.6版本,前10个字节为[66 4d 26 cc c9 b8 97 82 db 3d]。对于3.4版本,前10个字节为[66 4d 26 c38c c389 c2b8 c297 c282 c39b 3d]。我无法弄清楚其中的差异,并且它会在Python 3.x中给出错误的结果。 - Jam One
如果您仔细阅读答案,我认为问题在于chr所使用的编码,因为如果您不使用它,就不会有任何区别。在您的新示例中,如果返回数组而不是字符串并打印十六进制值,则可以获得正确的输出。请参见Python2Python3 - bracco23

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接