简体   繁体   中英

How does this recursive binary codes function work?

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

Currently learning recursion and confused as to how this function exactly works. It's supposed to return a list of strings of binary code of length r (as per the docstring) using the knowledge that you can add 0 and 1 to each 'binary code' to obtain the amount of strings in the next one.

Now where I'm confused is the small = codes(r-1) part

If I trace this through, it seems to just continually call the function until 'r == 0' is true where in that case, it ends off returning empty? Appending 0 and 1 to an empty list would seemingly only give you ['0', '1']. How does this function manage to return all binary codes of length r using that base case.

Let's look at this for r=2:

codes(2)

r is not 0, so we don't return anything. small get's assigned the return value of codes(1) . So to continue, we have to look at what codes(1) returns first.

codes(1)

Again, r is not 0. So the small inside this call is set to codes(0) . We have to look at what codes(0) returns.

codes(0)

This is hardcoded to return [''] . Let's go back to the execution of codes(1)

codes(1) (cont.)

small was set to [''] , now we iterate over every element of that list, but first, we define an empty list lst . small has only one element, '' . So we append two elements to lst : '' + '0' (which is just '0' ), and likewise '1' .

Then we return the list. So now we know that codes(1) returns ['0', '1'] . Let's go back to the execution of codes(2)

codes(2) (cont.)

small gets assigned the result of codes(1) , which we now know to be ['0', '1'] . Now we initialize an empty list lst again, and iterate over small . For every element in small (we have two), we append two elements to lst : That means to 0 we append both 0 and 1 to obtain 00 and 01 , and the same for 1 , to obtain 10 and 11 .

Therefore, codes(2) returns ['00', '01', '10', '11'] .

In general you will see that for each element in the result of codes(n) , codes(n+1) will return two elements: That element with 0 and 1 appended, respectively. So the length of the returns list always doubles, as it should.

It is important to understand that although the names small and lst are fixed, they refer to different objects in each call of codes , I think that might be the cause of your confusion.

The key to a recursive function is to know when to quit! Each recursive function, or at least one member of a group of mutually-recursive functions, will have a test that simply says, "This is the end, or start, or bottom, or top of whatever, and so the result is a constant, or an empty string, or a null list, or whatever."

Terminating

Your termination condition is r == 0 . And when asked for all binary strings of length zero, you are returning [''] - a list containing the empty string. Why? Because there are no such strings, but in order to make a longer string (see below) we need a string to append to.

Iterating

When not in a "this is the end" case, the recursive function needs to compute "one more step" in the process. Since the terminating condition for your function is based on the length of the string, your iterating condition will probably also be based on string length. In this case, you recurse by making the string shorter. So you iterate by making the (shortened) string longer.

If you have a binary string like '0', what are all the possible binary strings that are one character longer than that? Well, they are either ['01', '00'] or ['10', '00'] depending on whether you want to make strings longer at the end or at the beginning.

So how do you make a list of binary strings of length N? Well, first you get every possible binary string of length N-1 and then you make two strings for each one of those, with a zero or a one attached.

How can you get every possible binary string of length N-1 ? You can call this function, codes(N-1) and it will return them. Don't worry about how!

So small = codes(r-1) is your function getting a list of strings that are one character shorter -- the r-1 part. Then you iterate over each one, and make two! One will be the string plus '0', the second will be the string plus '1'. Once you have iterated over all the small -er strings, you have a list of longer strings. You can pass this result out to whoever asked for it (which might be yourself, trying to make even longer strings).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM