Python 这个递归二进制代码函数是如何工作的?

Python 这个递归二进制代码函数是如何工作的?,python,recursion,Python,Recursion,目前正在学习递归,对于这个函数到底是如何工作的感到困惑。它应该返回一个长度为r的二进制代码字符串列表(根据docstring),您可以将0和1添加到每个“二进制代码”中,以获得下一个“二进制代码”中的字符串数量 现在我感到困惑的是小=代码(r-1)部分 如果我对此进行跟踪,它似乎只是不断地调用函数,直到'r==0'为真,在这种情况下,它最终返回空?将0和1添加到空列表中似乎只能得到['0','1']。该函数如何使用该基本情况返回长度为r的所有二进制代码。让我们看看r=2的情况: 代码(2) r不

目前正在学习递归,对于这个函数到底是如何工作的感到困惑。它应该返回一个长度为r的二进制代码字符串列表(根据docstring),您可以将0和1添加到每个“二进制代码”中,以获得下一个“二进制代码”中的字符串数量

现在我感到困惑的是小=代码(r-1)部分


如果我对此进行跟踪,它似乎只是不断地调用函数,直到'r==0'为真,在这种情况下,它最终返回空?将0和1添加到空列表中似乎只能得到['0','1']。该函数如何使用该基本情况返回长度为r的所有二进制代码。

让我们看看r=2的情况:

代码(2)
r不是0,所以我们不返回任何内容
small
get被分配了
code(1)
的返回值。所以为了继续,我们必须先看看
code(1)
返回的内容

代码(1)
同样,r不是0。因此,此调用中的
small
设置为
codes(0)
。我们必须查看
code(0)
返回的内容

代码(0)
这是硬编码以返回
['']
。让我们回到执行
code(1)

代码(1)
(续)
small
设置为
['']
,现在我们迭代该列表的每个元素,但首先,我们定义一个空列表
lst
<代码>小只有一个元素,
'
。因此,我们将两个元素附加到
lst
'+'0'
(这只是
'0'
),同样地
'1'

然后我们返回列表。现在我们知道
codes(1)
返回
['0','1']
。让我们回到执行
code(2)

代码(2)
(续)
small
获得
代码(1)
的结果,我们现在知道它是
['0','1']
。现在我们再次初始化一个空列表
lst
,并在
small
上迭代。对于
small
(我们有两个)中的每个元素,我们将两个元素附加到
lst
:这意味着
0
我们将
0
1
附加到
00
01
,对于
1
,我们将这两个元素附加到
0
中,以获得
10
11

因此,
codes(2)
返回
['00','01','10','11']
。 通常,您会看到,对于
codes(n)
结果中的每个元素,
codes(n+1)
将返回两个元素:分别附加了
0
1
的元素。因此,返回列表的长度总是应该加倍


重要的是要理解,尽管名称
small
lst
是固定的,但它们在每次调用
code
时都指向不同的对象,我认为这可能是造成混淆的原因。

递归函数的关键是知道何时退出!每个递归函数,或一组相互递归函数中的至少一个成员,都将有一个测试,该测试只会说,“这是任何函数的结束、开始、底部或顶部,因此结果是一个常量、一个空字符串或一个空列表,或其他任何内容。”

终止

您的终止条件是
r==0
。当要求所有长度为零的二进制字符串时,您将返回一个包含空字符串的列表。为什么?因为没有这样的字符串,但是为了生成一个更长的字符串(见下文),我们需要一个附加的字符串

迭代

如果不是在“到此结束”的情况下,递归函数需要计算过程中的“更多步骤”。由于函数的终止条件基于字符串的长度,因此迭代条件也可能基于字符串长度。在本例中,通过缩短字符串来递归。因此,您可以通过使(缩短的)字符串变长来进行迭代

如果您有一个像“0”这样的二进制字符串,那么比它长一个字符的所有可能的二进制字符串是什么?它们是['01','00']或['10','00'],这取决于你是想让字符串在结尾还是开头变长

那么,如何列出长度为N的二进制字符串呢?首先,你得到每一个可能的长度为N-1的二进制字符串,然后你为每一个字符串生成两个字符串,附加一个0或一个1

如何获得长度为N-1的所有可能的二进制字符串?您可以调用此函数,
codes(N-1)
,它将返回它们。别担心怎么做


因此
small=codes(r-1)
是您的函数获取的字符串列表短一个字符--
r-1
部分。然后对每一个进行迭代,得到两个!一个是字符串加上“0”,第二个是字符串加上“1”。迭代了所有
小的
-er字符串后,就有了一个较长字符串的列表。您可以将此结果传递给任何请求它的人(可能是您自己,试图制作更长的字符串)。

“不必担心如何”。正是这一部分在困扰着我。在不知道内部发生了什么的情况下,就把它当作理所当然的工作,虽然现在我想这是有意义的,但对我来说,它没有那么直观的意义。诀窍是,递归函数将以两种方式之一工作-要么你将得到终止情况,要么你将得到一个迭代情况。因此,不要担心它在一个级别上是如何工作的。只是担心它在这个级别上是如何工作的。
def codes(r):
  '''(int) -> list of str

  Return all binary codes of length r.

  >>> binary_codes(2)
  ['00', '01', '10', '11']
  '''
  if r == 0:
    return ['']
  small = codes(r-1)
  lst = []
  for item in small:
    lst.append(item + '0')
    lst.append(item + '1')
  return lst