Question

I would like to create a default value in this python class. But when I try and do it I get an error that says, "self is not defined"

I know the answer is something simple, yet it eludes me at the moment. Anyone know why I cannot add a default parameter here?

Thanks in advance for your replies!

class Sort(object):
    def __init__(self, lst):
        self.lst = lst

    def halve(self, l = self.lst):### this line <--------------
        n1 = l[:len(l) / 2]
        n2 = l[len(l) /2:]
        return (n1,n2)
Was it helpful?

Solution

Unfortunately you need to designate a None default and check inside the method whether it's been passed in

class Sort(object):
    def __init__(self, lst):
        self.lst = lst

    def halve(self, l=None):
        if l is None: l = self.lst
        n1 = l[:len(l) / 2]
        n2 = l[len(l) /2:]
        return (n1,n2)

The parameters to a function are established when the function is created, not when it's called, so self.lst doesn't yet exist.

Also, see the "Principle of Least Astonishment"

OTHER TIPS

A better way to go about this, perhaps, would be:

def halve(self,l=None):
    if l is None:
        l = self.lst
    # code

As an aside: please don't name variables l el or O oh or I eye. They look like 1s and 0s in certain fonts and make things more difficult for everyone. If you want to signify that it's a generic list, use lst just as you have for your class variable! Better, name it by what it signifies: is this a list of grades? grade_list. Is it a list of numbers? numbers. Even if it's just input_list it's at least more readable than lst and FAR more readable than l

Since it is one of the method's parameters, self will only be defined inside Sort.halve, not on the line that declares it. This means that you cannot access self.lst until you are inside the method.

As a workaround, you can do something like this:

def halve(self, l=None):
    if l is None:
        l = self.lst
    n1 = l[:len(l) / 2]
    n2 = l[len(l) /2:]
    return (n1,n2)

The above code assigns the l parameter of Sort.halve a default value of None. When the method is invoked, it will use the if-statement to see if the caller supplied an argument for it or not. If so, it will keep l equal to that. Otherwise, it will assign l to self.lst.

Even if it does not seem useful for your purpose, you can avoid using None as a default placeholder, as you can use *args to collect all arguments in one list:

def halve(self, *args):
    if not args: # if arg is an empty list / no arguments given
        lst = self.lst
    else:
        lst = args[0]
    # code

or in one line:

def halve(self, *args):
    lst = self.lst if not args else args[0]
    # code

Others have shown how you can deal with your problem, but I would like to clear up exactly why your code isn't working.

Imagine you have the code:

def foo(obj, y = obj.x):
    pass

This won't work for the same reason that the following won't work:

def foo(x, y = x+2):
    pass

The key to your confusion, I think, is that there is nothing special about the name "self". It is easy to think that "self" is a key word that refers to the object (like in ruby, for instance), but it's not. In Python, object's methods automatically pass the object as the first parameter, and it just happens to be conventional to call this first parameter "self".

If you have a class, object, and method call like:

class A(object):
    def foo(self, x, y):
        pass
a = A()
a.foo(1, 2)

You can basically think of the method call as implicitly calling:

a.foo(a, 1, 2)

Which isn't the most careful way of putting it, but I think it makes the idea clear enough.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top