4

I am running into a problem writing recursive member functions in Python. I can't initialize the default value of a function parameter to be the same value as a member variable. I am guessing that Python doesn't support that capability as it says self isn't defined at the time I'm trying to assign the parameter. While I can code around it, the lack of function overloading in Python knocks out one obvious solution I would try.

For example, trying to recursively print a linked list I get the following code for my display function;

    def display(self,head = -1):
       if head == -1:
          head = self.head 

       if not head:
          return

       print head,

       self.display(head.link)

While this code works, it is ugly. The main function looks like this:

def main():
    l = List();
    l.insert(3);
    l.insert(40);
    l.insert(43);
    l.insert(45);
    l.insert(65);
    l.insert(76);

    l.display()

if __name__ == "__main__":
    main()

If I could set the display function parameter to default to self.head if it is called without parameters then it would look much nicer. I initially tried to create two versions of the function, one that takes two parameters and one that takes one but as I said, Python doesn't support overloading. I could pass in an argument list and check for the number of arguments but that would be pretty ugly as well (it would make it look like Perl!). The trouble is, if I put the line head = self.head inside the function body, it will be called during every recursive call, that's definitely not the behavior I need. None is also a valid value for the head variable so I can't pass that in as a default value. I am using -1 to basically know that I'm in the initial function call and not a recursive call. I realize I could write two functions, one driving the other but I'd rather have it all self contained in one recursive function. I'm pretty sure I'm missing some basic pythonic principle here, could someone help me out with the pythonic approach to the problem?

Thanks!

1
  • Please correct the indentation of the display function. Commented May 24, 2013 at 15:46

1 Answer 1

3

I don't really see what's wrong with your code. If you chose a falsy default value for head, you could do: head = head or self.head which is more concise.

Otherwise, this is pretty much what you have to do to handle default arguments. Alternatively, use kwargs:

def display(self,**kwargs):
    head = kwargs.get("head", self.head)

    if not head:
        return

    print head,

    self.display(head=head.link) # you should always name an optional argument,
                                 # and you must name it if **kwargs is used.
Sign up to request clarification or add additional context in comments.

7 Comments

I was trying to write it like this: def display(self,head=self.head), is that supposed to be allowed? My interpreter complains it doesn't know what 'self' means (kind of a philosophical dilemma :) )
@user2418063 No, that's not possible, which is why I don't talk about it. It's not possible because defaults are evaluated at class creation time, not function call time.
The default values for function parameters are resolved and fixed when the function is first interpreted and converted in to a function object. At that time, self doesn't exist, and besides, it wouldn't be a dynamic value as you'd want anyway. self is just the name used by convention to receive the implicit first argument of bound member methods, it has no intrinsic special meaning, and doesn't exist out of the scope where it is defined, namely inside the method for which it is an argument.
ok, I went with the kwargs approach, just one other change was needed to the code. Where I call self.display(head.link) I needed to change it to: self.display(head=head.link). I don't think the first approach would work because None is a valid value so the evaluation would cause an infinite loop at the terminating case. thanks!
Perfect example of using keyword arguments!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.