在Lutz';s";“学习Python”;

在Lutz';s";“学习Python”;,python,ascii,ord,Python,Ascii,Ord,我无法理解本书中给出的ord()函数的示例实现: >>> B = '1101' # Convert binary digits to integer with ord >>> I = 0 >>> while B != '': ... I = I * 2 + (ord(B[0]) - ord('0')) ... B = B[1:] ... >>> I 13 特别是我不明白我们通过这个计算“I=I*2+(ord(B[0])-o

我无法理解本书中给出的ord()函数的示例实现:

>>> B = '1101' # Convert binary digits to integer with ord
>>> I = 0
>>> while B != '':
... I = I * 2 + (ord(B[0]) - ord('0'))
... B = B[1:]
...
>>> I
13
特别是我不明白我们通过这个计算“I=I*2+(ord(B[0])-ord('0')”)实现了什么?有人能一步一步地解释一下这个程序是做什么的吗?

表达式
(ord(B[0])-ord('0'))
是一种非常麻烦的
int(B[0])

函数返回单个字符串的Unicode码点的数值。对于拉丁字母表中的数字和字符,这是ASCII值,介于0和127之间。对于更多的外来字符(如重音元音或汉字),您将获得更大的数字。ASCII字符集的一个特点是数字字符按顺序排列。零是字符48,一个是字符49,依此类推。这意味着您可以对
ord
值进行数学运算,这可能对应于对数字本身进行数学运算。如果从某个其他数字字符的
ord
中减去
ord('0')
,您将得到该其他字符的值

但大多数情况下,Python有更好的方法来做到这一点。如果您使用
int
将字符串转换为整数,而不是使用
ord
进行数学运算,则会更加清晰。我不知道你正在读的那本书为什么会建议你这样做,除非练习的重点是学习
ord
。实际上,在代码示例中有很多奇怪的东西。使用
for
循环是迭代字符串字符的一种更自然的方式,而不是在不断查找字符串的第一个字符时使用切片和while循环

如果我不能使用
int(some_string,2)
将二进制字符串转换为数字,我会写:

def convert_binary_to_int(bin_str):
    val = 0
    for char in bin_str:
        val *= 2
        val += int(char) # or maybe use char == '1', if you can't call int at all
    return val

正如我在代码中所评论的,如果您根本不能使用
int
,那么转换每个二进制数字的替代方法可能是
char='1'
,它将是
True
False
。这些值分别等于
1
0
,这实际上是您想要的数值

所以我找到了问题的答案。我无法理解这段代码背后的数学原理,为什么我们需要从0开始,然后乘以2,等等。结果证明,这只是重复除以2方法的相反结果。例如,13是二进制的1101,下面是转换它的一种方法

    13|2  rem 1
    6 |2  rem 0
    3 |2  rem 1
    1 |2  rem 1
    0
现在我们只需要从底部开始,这意味着

    0 * 2 + rem 1 = 1
    1 * 2 + rem 1 = 3
    3 * 2 + rem 0 = 6
    6 * 2 + rem 1 = 13

我猜我的问题措辞可能不正确。

这不是
ord
的“实现”;它使用的是
ord
。至于它是做什么的,你试过阅读文档吗?请特别重复介绍教程。堆栈溢出不是教程资源;“向我解释此代码”不是合适的请求。自己追踪代码;如果有一个特别的步骤让你困惑,那么把你不理解的细节贴出来。我知道ord是做什么的,它返回一个字符的ascii码点,我就是不明白这个计算是从哪里来的?为什么我们需要从0开始,然后出于某种原因将其乘以2,并将0和0或1和0之间的差值相加?我已经跟踪了代码,计算很好,我能做的,但是对meThis来说没有任何意义。看起来有人试图尽可能直接地将一些C代码转换成Python。
B=B[1:]
与递增
char*
的模拟效果很差,
ord
和减法看起来像是
某些字符的翻译-'0'
,而
while
则像是在空终止符处停止。