2

code:

class Node:
    def __init__(self, key, children=[]):
        self.key = key
        self.children = children

    def __repr__(self):
        return self.key

execute:

root = Node("root")
child = Node("child")
root.children.append(child)
print child.children
print root.children[0].children

result:

[child]
[child]

This is really weird, why?

Python's version is 2.7.2.

LeoDT
  • 80
  • 6
  • 6
    Mutable object as default value! `def __init__(self, key, children=None): \\ children=children or []` – Aleksei astynax Pirogov Jun 25 '12 at 10:13
  • 1
    No, see this question: http://stackoverflow.com/q/1132941/623518 – Chris Jun 25 '12 at 10:15
  • 1
    @LeoDT: Not a bug. More like surprising feature. If you think about it hard enough, it makes sense why it would work like that. – cha0site Jun 25 '12 at 10:19
  • The default value is a property of the _function object_. If you change it, you change it on the function object, so you change it for all calls to the function. – Katriel Jun 25 '12 at 10:34

2 Answers2

5

You shouldn't use mutable objects as default value of arguments (unless you exactly know what you're doing). See this article for explanation.

Instead use:

class Node:
    def __init__(self, key, children=None):
        self.key = key
        self.children = children if children is not None or []
Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
  • alternatively: `self.children = children if children is not None else []` or `self.children = [] if children is None else children`. – glglgl Jun 25 '12 at 10:25
  • 1
    `children or []` is not quite the same as `if children is not None`, because there are many false values which are not `None`. This may matter to you, or it may not, but the usual idiom is the latter. – Katriel Jun 25 '12 at 10:34
0
class Node:
    def __init__(self, key,children): # don't use children =[] here, it has some side effects, see the example below
        self.key = key
        self.children =children

    def __repr__(self):
        return self.key

root = Node("root",[])
child = Node("child",[])
root.children.append(child)
print root.children
print root.children[0].key

output:

[child]
child

example:

def example(lis=[]):
    lis.append(1) #lis persists value
    print(lis)
example()
example()
example()

output :

[1]
[1, 1]
[1, 1, 1]
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504