2

I'm writing a Python class based on list. The constructor builds a list based on two other lists that are passed as parameters. The logic is roughly: copy list A to the new instance, then iterate over list B, adding some entries and using others to modify entries from list A.

I've got two versions of the constructor. In the first, list A and list B were processed by loops. Then I decided to get clever; I used a comprehension to replace the loop that adds list A to the new instance.

The first version of the constructor works perfectly. The second version returns an empty list, even though I can look at the value of self in the debugger immediately before the constructor ends, and see that it's correct.

Why is this happening, and what can I do to make the second version work?

Here is the code that makes the second version misbehave. It copies list A to the new instance, then iterates over the instance to update data in a dictionary that represents the items in list B. ba is list A; getkey is a function (passed as a parameter) which derives a dictionary key from a list element; _dictb is a dictionary that contains an element for each element in list B.

self = [ [bae,None] for bae in ba ]  # Copy list A to self
for n in xrange(0,len(self)) :       # Iterate over list B
    _key = getkey( self[n][0])
    if _dictb.has_key(_key) :
        _dictb[_key] = n

In the first version, which works, the code above is replaced by this; the operations performed and the meanings of the variables are the same:

for bae in ba :
    _key = getkey(bae)
    if _dictb.has_key(_key) :
        _dictb[_key] = len(self)
    self.append( [bae,None] )
1

2 Answers 2

3

I will assume you're really talking about Python constructors here and have, for some weird reason, omitted the class definition and the def __init__ statement. In the "second version," which is the first code snippet you gave, your first line assigns a list to a local variable named "self". That DOES NOT replace the object being constructed with a different object. The thing that gets returned from a constructor is the new object, not the variable self.

Solution: don't assign to self. Ever. Don't even think about it.

Also you can't use a list comprehension to create a subclass of list, only an instance of list. Your "first version" (second code snippet) works and there is nothing wrong with it.

Aside: you should replace "_dictb.has_key(key)" with "key in _dictb."

Sign up to request clarification or add additional context in comments.

Comments

2

If you are sub-classing a list you don't want to re-assign the object self in your constructor. This will not affect the internal contents of the list itself but replace the reference of self to be the new list comprehension you just created.

In other words it won't have the desired effect you're after.

Instead do something like this:

class MyList(list):

    def __init__(self, xs):
        super(MyList, self).__init__()

        for x in xs:  # Assign all values of xs to the list object ``self``
            self.append(x)

Comments

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.