0

I have a function, create, which accepts these arguments:

create(self, name, val={})

It is part of a class which has an attribute also named val, so note that val and self.val are two different objects.

Somehow, the value of val has been replaced with self.val, which is leading to some recursion issues in my module.

The module in question, named pyndb, basically takes a dictionary and represents each key with a custom Node object. These objects then do the same process (if the key's value is another dictionary) for all of the keys they hold. If it helps, I've documented the whole module here.

If you take a look at the module and the specific process to reproduce this error as I detail here, you will notice that this only occurs when trying to create the 3rd object inwards of the main class. The value of said object should be an empty dictionary, as I did not change the default value of the val argument. However, if I set val to an empty dictionary manually, there are no issues.

The part that stumps me the most is why this only affects the 3rd Node inwards.

The source code for the module is in the GitHub repository which I linked above, and the module is available for install with pip:

pip3 install pyndb

Any help would be greatly appreciated.

jvadair
  • 35
  • 1
  • 7
  • 3
    1) Please update your question to include a self-contained [minimal, reproducible example](/help/minimal-reproducible-example). We can't accept links to external sites. 2) It looks like your issue may be due `create` using a mutable default argument. If `create` assigns `val` to `self.val` anywhere, you may end up with `val` referencing the same object as `self.val` on all subsequent calls that use the default argument. See [“Least Astonishment” and the Mutable Default Argument](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) – Brian61354270 Aug 04 '21 at 02:04
  • This makes sense now that I have read the accepted answer on that post. I didn't realize that keyword arguments were only defined once, and could be changed like this. Thanks for the help – jvadair Aug 04 '21 at 02:29

1 Answers1

2

I'm not sure I specifically understand the question, but I suspect that your issue is coming from using a mutable object as a default variable. To give you an example imagine I have a function which goes

def add_to_list(item, l=[]):
    l.append(item)
    return l

If I then call it once I get what you expect

>>> add_to_list(1)
[1]

BUT, this has now permanently altered the value of the l default variable, which means that if I now type

>>> add_to_list(2)
[1,2]

I get both elements instead of one.

To fix your problem I'd suggest

def create(self, name, val=None):
    if not val:
        val = {}

As a workaround.

Milan
  • 344
  • 1
  • 10