2

I have a model for tree like data (id - parent). And I have recursion method, to get all children for current page.

children = []    
class Page(models.Model):
    ...
    def get_children(self, include_self=True):
        global children
        if include_self:
            children.append(self.id)
        for c in Page.objects.filter(parent=self.id):
            c.get_children(True)
        return children

I use console for a test:

>>> from pages.models import Page
>>> q = Page.objects.get(id=10) #I get a page with children.
>>> q.get_children(False)

It works fine:

[12L, 11L]

But if I use this method next time,

q.get_children(False)

result will be:

[12L, 11L, 12L, 11L]

I want always have:

 [12L, 11L]

What is do wrong? How I should reset the variable but safe scope of recursion?

EDIT:

Correct recursion function is:

def get_children(self, include_self=True, children = None):
   if children is None:
        children = []
    if include_self:
        children.append(self.id)
    for c in Page.objects.filter(parent=self.id):
        c.get_children(True)
    return children
Weltkind
  • 687
  • 5
  • 9
  • You are assuming that `children=[]` creates a new list every call; it doesn't. See the duplicate. Function defaults are created *once*. – Martijn Pieters Mar 05 '16 at 14:32
  • The solution: use `children=None` (set to a sentinel), and in the function test for the sentinel, `if children is None: children = []`. – Martijn Pieters Mar 05 '16 at 14:34
  • This not working too. – Weltkind Mar 05 '16 at 14:45
  • I add this: def get_children(self, include_self=True): global children if children is None: children = [] if include_self: children.append(self.id) for c in Page.objects.filter(parent=self.id): c.get_children(True) return children – Weltkind Mar 05 '16 at 14:45
  • Why would creating a *global* work? You then just shifted the problem to a different place (from a shared function default to a global). Please do read the duplicate carefully. – Martijn Pieters Mar 05 '16 at 14:47

0 Answers0