Using self.xxxx as a default parameter - Python
Solution 1
larsmans answered your first question
For your second question, can you simply look before you leap to avoid recursion?
def makeList(self, aNode=None):
if aNode is None:
aNode = self.root
treeaslist = [aNode.data]
if aNode.lChild:
treeaslist.extend(self.makeList(aNode.lChild))
if aNode.rChild:
treeaslist.extend(self.makeList(aNode.rChild))
return treeaslist
Solution 2
It doesn't work because default arguments are evaluated at function definition time, not at call time:
def f(lst = []):
lst.append(1)
return lst
print(f()) # prints [1]
print(f()) # prints [1, 1]
The common strategy is to use a None
default parameter. If None
is a valid value, use a singleton sentinel:
NOTHING = object()
def f(arg = NOTHING):
if arg is NOTHING:
# no argument
# etc.
Solution 3
If you want to treat None
as a valid argument, you could use a **kwarg
parameter.
def function(arg1, arg2, **kwargs):
kwargs.setdefault('arg3', default)
arg3 = kwargs['arg3']
# Continue with function
function("amazing", "fantastic") # uses default
function("foo", "bar", arg3=None) # Not default, but None
function("hello", "world", arg3="!!!")
I have also seen ...
or some other singleton be used like this.
def function(arg1, arg2=...):
if arg2 is ...:
arg2 = default
Related videos on Youtube
chrisheinze
Updated on July 16, 2021Comments
-
chrisheinze almost 3 years
I'm trying to simplify one of my homework problems and make the code a little better. What I'm working with is a binary search tree. Right now I have a function in my
Tree()
class that finds all the elements and puts them into a list.tree = Tree() #insert a bunch of items into tree
then I use my makeList() function to take all the nodes from the tree and puts them in a list. To call the
makeList()
function, I dotree.makeList(tree.root)
. To me this seems a little repetitive. I'm already calling the tree object withtree.
so thetree.root
is just a waste of a little typing.Right now the makeList function is:
def makeList(self, aNode): if aNode is None: return [] return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild)
I would like to make the aNode input a default parameter such as
aNode = self.root
(which does not work) that way I could run the function with this,tree.makeList()
.First question is, why doesn't that work?
Second question is, is there a way that it can work? As you can see themakeList()
function is recursive so I cannot define anything at the beginning of the function or I get an infinite loop.EDIT Here is all the code as requested:
class Node(object): def __init__(self, data): self.data = data self.lChild = None self.rChild = None class Tree(object): def __init__(self): self.root = None def __str__(self): current = self.root def isEmpty(self): if self.root == None: return True else: return False def insert (self, item): newNode = Node (item) current = self.root parent = self.root if self.root == None: self.root = newNode else: while current != None: parent = current if item < current.data: current = current.lChild else: current = current.rChild if item < parent.data: parent.lChild = newNode else: parent.rChild = newNode def inOrder(self, aNode): if aNode != None: self.inOrder(aNode.lChild) print aNode.data self.inOrder(aNode.rChild) def makeList(self, aNode): if aNode is None: return [] return [aNode.data] + self.makeList(aNode.lChild) + self.makeList(aNode.rChild) def isSimilar(self, n, m): nList = self.makeList(n.root) mList = self.makeList(m.root) print mList == nList
-
Andreas Jung about 13 yearsWhat do you want with 'self' within a module level method? This makes absolutely no seense. If makeList2() is a method of class then please provide correct code and not snippets without context.
-
chrisheinze about 13 yearsmakeList2() was suppose to be makeList(), I edited it
-
chrisheinze about 13 yearsHow does this make no sense? I'm trying to use my makeList() function simpler by using a default parameter for the root of the tree instead of having to call it.
-
william_grisaitis about 10 yearsI agree with @crh878 that this makes sense. I tried it myself, also for creating a binary search tree. No joke...
-
Stevoisiak over 6 yearsPossible duplicate of Using self.* as default value for a method
-
-
Admin about 13 yearsYou can omit the
Sentinel
. Just useNOTHING = object()
. Guaranteed to yield a unique singleton you can check for viais
. -
Glenn Maynard about 13 yearsI'd strongly advise against making
foo(1, None)
andfoo(1)
do different things. -
Fred Foo about 13 years@Glenn: with a one-arg function that must deal with arbitrary objects, it can make sense sometimes.
-
chrisheinze about 13 yearsOk, I understand why it doesn't work and also how your first code segment continually appends whatever value you add but I'm not fully following what's going on in the second code segment.
-
Fred Foo about 13 years@crh878: the point about using
None
is the most important. The second part constructs an objectNOTHING
, uses that as the default argument and checks whether that exact object was passed in. If you hideNOTHING
(don't export it from your module), it cannot be passed in by client code.is
compares objects by memory address. -
chrisheinze about 13 years@larsmans ok I'm getting it. So if you something like a list, Python will continue to add on to that list even after it is done running that function, thus the function is useless if it is ran more than once? But if you assign the value to None and then change it, the function is reusable?
-
Fred Foo about 13 years@chr878: you've got it. But actually, the
list
version may be useful sometimes, if you remember this behavior and document it well; it's very like introducing a global variable. I've seen libraries do this. But theNone
version is far more common. -
Charlestone about 7 yearsWhy we should use this instead of None?