-1

I'm trying to create a character frequency dictionary via recursion and it has an empty dicionary as a default parameter. But when I run it consecutively, like defining 2 variables consecutively with the function, it uses a different initial value for the dictionary than an empty one.

def freq_dict(list1, a={}):
        if len(list1)>0:
            char1= list1[0]
            if char1 in a.keys():
                a[char1]+=1
                n=a.copy()
                list1=list1[1:]
                return freq_dict(list1, n)
            else:
                a[char1]=1
                n=a.copy()
                list1=list1[1:]
                return freq_dict(list1, n)
        else:
            return a
            
a=freq_dict([1, 2, 2, 1])
b=freq_dict([1, 2, 2, 1])

print(a)
print(b)

This is the code. The expected output would be:

{1: 2, 2: 2}
{1: 2, 2: 2}

But the output I receive is:

I tried printing the dictionary as it was being created and this is the output I got:

The first line is the first time the function is called and it works fine, a starts out empty and reaches the expected value. But in the second line, a begins as {1:1}, which makes no sense because I put the print statement above everything else, it's the first line in the function, yet it uses a={1:!}.

Nick
  • 138,499
  • 22
  • 57
  • 95
  • this is not recursive. You are just calling the same function twice, but each time passing in different values (dicts) as the arguments... recursive would be when the function returns the value and this is recycled into the next function call. – D.L Oct 29 '22 at 07:56
  • Is that why I'm running into errors? – Arsh Kulshrestha Oct 29 '22 at 08:16
  • also list1 is immutable but being treated as mutable.... are you just trying to count the occurrences in the list ? if so, the solution can be simplified a lot. – D.L Oct 29 '22 at 08:30
  • `from collections import Counter; Counter([1,2,2,1])` – Nick Oct 29 '22 at 11:23
  • See also https://stackoverflow.com/questions/13087344/python-function-default-parameter-is-evaluated-only-once and https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Nick Oct 29 '22 at 11:30

1 Answers1

0

This is a cleaner version of what the question tries to solve for.

In particular:

  1. there was no need to select elements from the list1, but instead iterate of the list.
  2. Also, to start again, pass in the second argument of a blank dict (otherwise it includes the previous list).
def freq_dict(list1, a={}):
    for i in list1:
        if i in a.keys():
            a[i] += 1
        else:
            a[i] = 1
        
    return a


# add first list            
x=freq_dict([1, 2, 2, 1])
print(x)

y = freq_dict([1, 2, 2, 1], a={})
print(y)

The result is:

{1: 2, 2: 2}
{1: 2, 2: 2}
D.L
  • 4,339
  • 5
  • 22
  • 45