Python3将Unicode String转换为int表示

时间:2012-09-27 16:09:04

标签: python string unicode python-3.x int

众所周知,计算机使用数字。我正在输入此文本,服务器会输出一个数字,当您想要读取它时,您将从服务器获取文本。

我怎么能独自完成这个?

我想用自己的算法加密某些东西,我的算法可以很好地处理整数,但现在我想加密一个字符串,我不知道如何将Unicode字符串转换为整数,反之亦然。

我正在使用Python 3.有没有人知道我的问题的优雅解决方案?

5 个答案:

答案 0 :(得分:12)

您正在寻找ord() function,我认为:

>>> ord('a')
97
>>> ord('\u00c2')
192

这将为您提供Unicode代码点的整数。

要转换整个字符集,请使用列表解析:

>>> [ord(c) for c in 'Hello World!']
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

相反的是chr() function

>>> chr(97)
'a'
>>> chr(193)
'Á'

请注意,当您加密最终解密文本时,通常将文本编码为带有character encoding的二进制表示。 Unicode文本可以使用不同的编码进行编码,具有不同的优点和缺点。这些天是Unicode文本UTF-8最常用的编码,但其他编码存在。

在Python 3中,二进制数据在bytes object中表示,您使用str.encode() method将文本编码为字节,然后使用bytes.decode()返回:

>>> 'Hello World!'.encode('utf8')
b'Hello World!'
>>> b'Hello World!'.decode('utf8')
'Hello World!'

bytes值实际上只是序列,如列表,元组和字符串,但由0-255的整数组成:

>>> list('Hello World!'.encode('utf8'))
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

就个人而言,在加密时,您希望对结果字节进行编码和加密。

如果所有这些看起来势不可挡或难以理解,那么这些关于Unicode和字符编码的文章可能会有所帮助:

答案 1 :(得分:11)

将Unicode字符串转换为数字的常用方法是将其转换为字节序列。 Unicode字符是纯抽象的,每个字符都有自己的编号;但是,有更多方法可以将数字转换为字节流。可能最通用的方法是将字符串编码为UTF-8编码。您可以选择多种方法从中获取整数。这是一个(我从Ivella借来了很好的字符串 - 我希望里面没有坏词:):

Python 3.2.1 (default, Jul 10 2011, 20:02:51) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> s = "Hello, World, عالَم, ދުނިޔެ, जगत, 世界"
>>> b = s.encode('utf-8')
>>> b
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c'

现在我们有字节序列,其中数字从128到255的那些显示为十六进制编码的转义序列。让我们将所有字节转换为十六进制代码作为字节串。

>>> import binascii
>>> h = binascii.hexlify(b)
>>> h
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'

我们可以将它看作是以十六进制表示法编写的大数字(如文本)。 int允许我们将它转​​换为抽象数字 - 在打印时 - 更通常转换为十进制表示法。

>>> i = int(h, 16)
>>> i
52620351230730152682202055464811384749235956796562762198329268116226267262806875102376740945811764490696968801603738907493997296927348108

现在您可以将其存储为数字,对其进行加密(尽管更常见的是加密较早的字节序列),然后将其转换回整数。请注意,没有多少语言(可能没有数据库)能够处理大整数。

让我们回到原来的字符串。首先将其转换为十六进制表示(字符串)。

>>> h2 = hex(i)
>>> h2
'0x48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> h3 = h2[2:]   # remove the 0x from the beginning
>>> h3
'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> type(h3)
<class 'str'>

我们必须删除0x,因为它只表示其余的是表示数字的十六进制字符。请注意,h3属于str类型。正如我们在Python 3中所见(见顶部),str表示Unicode字符串。下一步是将六进制数字对转换回字节。我们试试unhexlify()

>>> binascii.unhexlify(h3)
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    binascii.unhexlify(h3)
TypeError: 'str' does not support the buffer interface

糟糕!它只接受字节串​​。然后,将Unicode中的每个hexa数字编码为bytestring中的hexa数字。要走的路是编码;然而,编码为ASCII是微不足道的。

>>> b2 = h3.encode('ascii')  # character by character; subset of ascii only
>>> b2
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c'
>>> b3 = binascii.unhexlify(b2)
>>> b3
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c'

现在我们有与第一个.encode('utf-8')之后相似的字节串。让我们使用逆操作 - 从UTF-8解码。我们应该得到与我们开始时相同的Unicode字符串。

>>> s2 = b3.decode('utf-8')
>>> s2
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界'
>>> s == s2   # is the original equal to the result?
True

:)

答案 2 :(得分:5)

来自python的文档:

  

binascii module包含许多转换方法   二进制和各种ASCII编码的二进制表示。

例如,您可以使用binascii.hexlify获取二进制字符串“LOL”的十六进制表示形式,并通过int内置函数将其转换为整数:

>>> binascii.hexlify(b"LOL")
b'4c4f4c'
>>> int(binascii.hexlify(b"LOL"), 16)
5001036

由于您需要将此应用于unicode字符串,因此首先需要将它们编码为二进制字符串。您可以使用方法str.encode来实现此目的:

>>> int(binascii.hexlify("fiŝaĵo".encode("utf-8")), 16)
7379646744164087151

就是这样。

反之亦然,您需要反转每一步。首先以十六进制表示形式将整数转换为二进制字符串(您可以使用format(int, "x")然后对其进行编码),将ascii中的十六进制转换为binascii.unhexlify,最后解码为utf-8:

>>> binascii.unhexlify(format(7379646744164087151, "x").encode("utf-8")).decode("utf-8")
'fiŝaĵo'

这是一个循序渐进的解释,如果你真的会使用这个设施,那么以功能的形式安排它们是个好主意。

答案 3 :(得分:1)

在Martijn Pieters给出的解决方案的基础上,你可以使你的字符串成为一个庞大的数字,Python 3可以很好地处理,因为它的int类型是任意大的(不是“计算机如何工作”,请参阅我的评论你的问题)。

给出字符数字代码列表:

>>> a = [ord(c) for c in 'Hello World!']
>>> print(a)
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]

从维基百科的Unicode页面知道最大的unicode字符数是10FFFF(十六进制),你可以这样做:

def numfy(s):
    number = 0
    for e in [ord(c) for c in s]:
        number = (number * 0x110000) + e
    return number

def denumfy(number):
    l = []
    while(number != 0):
        l.append(chr(number % 0x110000))
        number = number // 0x110000
    return ''.join(reversed(l))

因此:

>>> a = numfy("Hello, World, عالَم, ދުނިޔެ, जगत, 世界")
>>> a
31611336900126021[...]08666956
>>> denumfy(a)
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界'

此0x110000(从10FFFF + 1)是不同的预见Unicode字符数(1114112,十进制)。如果你确定你只使用英文字母,你可以在这里使用128,如果你使用一些带有重音的拉丁语,使用256是安全的。无论哪种方式你的数字都会小得多,但它将无法使用表示每个Unicode字符。

答案 4 :(得分:-1)

这会将每个字符转换为数字......

s="hello \u2020"
print [ord(c) for c in s]
相关问题