简体   繁体   中英

how to fix the _getitem__ method

def pnamedtuple(type_name, field_names, mutable=False):
    pass

    class type_name:
        def __init__(self, x, y):
            self.x = x
            self.y = y
            self._fields = ['x','y']
            self._mutable = False

        def get_x(self):
            return self.x

        def get_y(self):
            return self.y

        def __getitem__(self,i):
            if i > 1 or i <0:
                raise IndexError
            if i == 0 or i == 'x':
                return self.get_x():
            if i == 1 or i == 'y':
                return self.get_y():

the getitem method to overload the [] (indexing operator) for this class: an index of 0 returns the value of the first field name in the field_names list; an index of 1 returns the value of the second field name in the field_names list, etc. Also, the index can be a string with the named field. So, for p = Point(1,2) writing p.get_x(), or p[0]), or p['x'] returns a result of 1. Raise an IndexError with an appropriate message if the index is out of bounds int or a string that does not name a field.

I am not sure how to fix the getitme function. below is the bsc.txt

c-->t1 = Triple1(1,2,3)
c-->t2 = Triple2(1,2,3)
c-->t3 = Triple3(1,2,3)
# Test __getitem__ functions
e-->t1[0]-->1
e-->t1[1]-->2
e-->t1[2]-->3
e-->t1['a']-->1
e-->t1['b']-->2
e-->t1['c']-->3
^-->t1[4]-->IndexError
^-->t1['d']-->IndexError
^-->t1[3.2]-->IndexError

can someone tell how to fix my _getitem _ function to get the output in bsc.txt? many thanks.

You've spelled __getitem__ incorrectly. Magic methods require two __ underscores before and after them.

So you haven't overloaded the original __getitem__ method, you've simply created a new method named _getitem_ .

Python 3 does not allow strings and integers to be compared with > or < ; it's best to stick with == if you don't yet know the type of i . You could use isinstance , but here you can easily convert the only two valid integer values to strings (or vice versa), then work only on strings.

def __getitem__(self, i):
    if i == 0:
        i = "x"
    elif i == 1:
        i = "y"

    if i == "x":
        return self.get_x()
    elif i == "y":
        return self.get_y()
    else:
        raise IndexError("Invalid key: {}".format(i))

your function is interesting, but there are some issues with it:

  1. In python 3 you can't compare string with numbers, so you first should check with == against know values and or types. For example

     def __getitem__(self,i): if i in {0,"x"}: return self.x elif i in {1,"y"}: return self.y else: raise IndexError(repr(i)) 
  2. But defined like that (in your code or in the example above) for an instance t1 this t1[X] for all string X others than "x" or "y" will always fail as you don't adjust it for any other value. And that is because

  3. pnamedtuple looks like you want for it to be a factory like collections.namedtuple , but it fail to be general enough because you don't use any the arguments of your function at all. And no, type_name is not used either, whatever value it have is throw away when you make the class declaration.

how to fix it?

  1. You need other ways to store the value of the fields and its respective name, for example a dictionary lets call it self._data

  2. To remember how you called yours field, use the argument of your function, for instance self._fields = field_names

  3. To accept a unknown number of arguments use * like __init__(self, *values) then verify that you have the same numbers of values and fields and build your data structure of point 1 (the dictionary)

Once that those are ready then __getitem__ become something like:

def __getitem__(self, key):
    if key in self._data:
        return self._data[key]
    elif isintance(key,int) and 0 <= key < len(self._fields):
        return self._data[ self._fields[key] ]
    else:
        raise IndexError( repr(key) )

or you can simple inherit from a appropriate namedtuple and the only thing you need to do is overwrite its __getitem__ like

def __getitem__(self,key):
    if key in self._fields:
        return getattr(self,key)
    return super().__getitem__(key)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM