views:

104

answers:

1

This is a continuation of one of my previous questions

Here are my classes.

#Project class     
class Project:
    def __init__(self, name, children=[]):
        self.name = name
        self.children = children
    #add object
    def add(self, object):
        self.children.append(object)
    #get list of all actions
    def actions(self):
        a = []
        for c in self.children:
            if isinstance(c, Action):
                a.append(c.name)
        return a
    #get specific action
    def action(self, name):
        for c in self.children:
            if isinstance(c, Action):
                if name == c.name:
                    return c
    #get list of all projects
    def projects(self):
        p = []
        for c in self.children:
            if isinstance(c, Project):
                p.append(c.name)
        return p
    #get specific project
    def project(self, name):
        for c in self.children:
            if isinstance(c, Project):
                if name == c.name:
                    return c

#Action class  
class Action:
    def __init__(self, name):
        self.name = name
        self.done = False

    def mark_done(self):
        self.done = True

Here's the trouble I'm having. If I build a big project with several small projects, I want to see what the projects are or the actions for the current project, however I'm getting all of them in the tree. Here's the test code I'm using (note that I purposely chose several different ways to add projects and actions to test to make sure different ways work).

life = Project("life")

playguitar = Action("Play guitar")

life.add(Project("Get Married"))

wife = Project("Find wife")
wife.add(Action("Date"))
wife.add(Action("Propose"))
wife.add(Action("Plan wedding"))
life.project("Get Married").add(wife)

life.add(Project("Have kids"))
life.project("Have kids").add(Action("Bang wife"))
life.project("Have kids").add(Action("Get wife pregnant"))
life.project("Have kids").add(Project("Suffer through pregnancy"))
life.project("Have kids").project("Suffer through pregnancy").add(Action("Drink"))
life.project("Have kids").project("Suffer through pregnancy").add(playguitar)

life.add(Project("Retire"))
life.project("Retire").add(playguitar)

life should have a few projects in it, with a few projects inside of those. The structure amounts to something like this (where indents are projects and -'s are actions)

Life
    Get Married
        Find wife
            - Date
            - Propose
            - Plan wedding
    Have kids
        - Bang wife
        - Get wife pregnant
        Suffer through pregnancy
            - Drink
            - Play guitar
    Retire
        - Play guitar

What I'm finding is that life.actions() is returning every action in the tree when it should return none. life.projects() is returning every project, even sub projects, when I only want 'Get Married', 'Have kids', and 'Retire'. What is it that I'm doing wrong?

+4  A: 

The problem is with your initialization of Projects:

 __init__(self, name, children=[]):

You only get one list, which is shared by all Projects you create without passing a value for children. See here for an explanation. You want to instead make the default None, and initialize an empty list whenever the value is None.

 __init__(self, name, children=None):
    if children is None:
       children = []
Matt G