0

I am having some problems generating a list for a class in Python. I know there is something simple I'm overlooking, but I just can't figure it out.

My basic code so far:

class Test:
    def  __init__(self,test):
        self.__test = test

My problem is that if I enter

t = Test([1,3,5])

things will work just fine, but if I add

t = Test()

I get an error that I didn't enter enough parameters.

I've tried adding

def __init__(self,test=[])

as a default parameter, which sort of works, but then I don't have unique lists.

I've been looking all over and I can't quite figure out what I'm doing wrong. Any help would be greatly appreciated.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
Jef
  • 3
  • 1
  • what do you mean with unique lists? – KillianDS Apr 20 '10 at 14:36
  • See here: http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument – balpha Apr 20 '10 at 14:36
  • 3
    Since you use a double-leading underscore name for your attribute, it's probably worth pointing out http://stackoverflow.com/questions/165883/python-object-attributes-methodology-for-access/166098#166098 – Thomas Wouters Apr 20 '10 at 14:46

3 Answers3

4

I'm not exactly sure what you're looking for, but you probably want to use None as a default:

class Test:
    def  __init__(self,test=None):
        if test is None:
            self.__test = []
        else:
            self.__test = test
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 2
    Your two branches are a little lopsided. Either assign to `self.__test` in the `is None` branch as well, or just do the assignment after the `if` without an `else`. – Thomas Wouters Apr 20 '10 at 14:45
  • This is where I was having trouble, I tried something similar, but wasn't using 'None' as the default for test. This fixed my program right up. Thanks a ton to everyone for the help and extra reading! – Jef Apr 20 '10 at 17:52
  • FYI: Personally, I prefer Thomas Wouters' answer. – Xavier Ho Apr 21 '10 at 14:07
3

You could use the following idiom:

class Test:
    def  __init__(self,test=None):
        self.__test = test if test is not None else []
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
  • @Thomas Wouters: I figured some people might feel that way. That's why I'm leaving my answer as-is. – Fred Larson Apr 20 '10 at 14:44
  • I'm not sure what's unclear about "yuck, ternary expression". I don't like the use of the ternary expression there. (Or, in fact, anywhere.) – Thomas Wouters Apr 20 '10 at 14:52
  • @Thomas, so you didn't use it in your answer. I find it entirely appropriate and readable. – SilentGhost Apr 20 '10 at 14:55
  • 1
    I agree that it's perfectly readable, and I think it's a poor reason for a down vote. – Fred Larson Apr 20 '10 at 14:57
  • Readability of code is important to me, so I *did* downvote -- I find the other answer (that isn't mine) to be better. Fortunately, differences of opinion are why we have sites like stackoverflow. – Thomas Wouters Apr 20 '10 at 15:00
3

Default arguments are evaluated once, when the function is defined, so when you do:

def __init__(self, test=[]):

the 'test' list is shared between all calls to __init__ that don't specify the test argument. What you want is commonly expressed so:

def __init__(self, test=None):
    if test is None:
        test = []

This creates a new list for each invocation where test is not passed an argument (or when it is passed None, obviously.)

Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • 1
    Thanks for the explanation, I knew that's what was happening, I just didn't know the proper way to alleviate that problem. I appreciate it greatly! – Jef Apr 20 '10 at 17:53