25

I've created a python program that makes a vector. Now i want to set an item using a function__setitem__ and__getitem__. So for example, ifvector = Vec()andvector[3] = 26would change an empty vector to[0, 0, 0, 26]. I need to override the__getitem__and__setitem__ I've listed the code below, but i'm having troubles with the get and set functions. Any advice?

class Vec:
    def __init__(self, length = 0):
        self.vector = [0]*length

    def __str__(self):
        return '[{}]'.format(', '.join(str(i) for i in self.vector))
        #This formats the output according to the homework.
        #Adds '[' and ']' and commas between each 0

    def __len__(self):
        return len(self.vector)

    def extend(self, newLen):
        self.vector.append([0]*newLen)
        return (', '.join(str(j) for j in self.vector))

    def __setitem__(self, key, item):
        self.vector[key] = item

    def __getitem__(self, key):
        return self.vector[key]
martineau
  • 119,623
  • 25
  • 170
  • 301
user3014014
  • 751
  • 3
  • 10
  • 20
  • 1
    what troubles are you having exactly? – mgilson Dec 03 '13 at 16:28
  • I'm not able to change keys and items that are in my vector as i thought i should be able to. Do you see anything? – user3014014 Dec 03 '13 at 16:38
  • @user3014014 I take it this is a learning exercise, and you can't just inherit from `list` as shown in [your other question](http://stackoverflow.com/questions/20338675/creating-vectors-with-python) ? – Jon Clements Dec 03 '13 at 16:39
  • Tip for the future: As shown [here](http://stackoverflow.com/a/9061024/2555451), `str.join` runs better with a list comprehension than it does with a generator expression. –  Dec 03 '13 at 16:41
  • Even if this is a learning exercise - I'm puzzled as to what you're supposed to be learning... At the moment all it's accounting to is duplicating `list`s interface and explicitly calling its implementation of methods... – Jon Clements Dec 03 '13 at 16:45
  • 2
    Please explain better than "am not able", it would be very useful to see a complete example and a stacktrace such as: >>> v = Vec() >>> v[3] = 26 Traceback (most recent call last): File "", line 1, in v[3] = 26 File "C:\Users\S\Desktop\test.py", line 18, in __setitem__ self.vector[key] = item IndexError: list assignment index out of range >>> –  Dec 03 '13 at 16:46
  • I'm entering v = Vec() >>> v[3] = 26. I want my output to read [0, 0, 0, 26], but it gives me an IndexError. – user3014014 Dec 03 '13 at 19:08

4 Answers4

12

You have several problems:

  1. extend is appending essentially a new vector to the end of the original, rather than increasing the length of the original. It's not clear that it needs to return a string representation of the modified vector (unless it's just for debugging purposes).

    def extend(self, newlength):
        # Assume newlength is greater than the old
        self.vector.extend([0] * (newlength - len(self)))
    
  2. __setitem__ needs to call extend if the key is too large.

    def __setitem__(self, key, item):
        if key >= len(self):
            self.vector.extend(key+1)
        self.vector[key] = item
    
  3. __getitem__ needs to access the underlying list, not use an undefined attribute

    def __getitem__(self, key):
        # It's probably better to catch any IndexError to at least provide
        # a class-specific exception
        return self.vector[key]
    
chepner
  • 497,756
  • 71
  • 530
  • 681
6

The problem is the vector you created has no length because of the default value given the length keyword argument in the __init__() method definition. Try this:

vector = Vec(4)
vector[3] = 26
print vector  # --> [0, 0, 0, 26]
martineau
  • 119,623
  • 25
  • 170
  • 301
2

It would be easier in __str__ if you do this

return str(self.vector)
Superior
  • 787
  • 3
  • 17
1

You need to adapt your __getitem__ and __setitem__ to delegate to the underlying list:

def __setitem__(self, key, item):
    self.vector[key] = item 
    # return doesn't make sense here

def __getitem__(self, key):
    # not sure what self.__key is ? Let's return value from index in `self.vector` instead
    return self.vector[key]
Jon Clements
  • 138,671
  • 33
  • 247
  • 280