简体   繁体   中英

Treat a single element list as a scalar in Python

¿Is it possible to define a subclass of a python list which allow the use of single-element list variables as if they were scalars?

For example I would like to be able to do:

class CustomList(list):
    ...
    ...

list1 = CustomList([2])
list2 = CustomList([3])
list3 = CustomList([4,5,6])
list4 = CustomList([{'foo':'bar'}])
list1 #should return list1[0]
list4['foo'] #should return list4[0]['foo'] = 'bar'
list1 + list2 #should return list1[0] + list2[0] = 5

but keeping the ability to use the list as normal:

for i in list3:
    print list[i]

Yes, but you would effectively need to override any methods you'd want it to work with.

When you call certain operators on objects like lists, you end up calling hidden methods on those objects. In the example you gave, result = list1 + list2 , the function that is actually called is list1.__add__(list2) . You can subclass list and override these methods, if you want. For example:

class CustomList(list):
    def __add__(self, value):
        if len(self) == 1 and len(value) == 1:
            return self[0] + value[0]
        else:
            return CustomList(list.__add__(self, value))

will treat list1 and list2 as scalars if they're both of length 1, and refer to the normal list functionality otherwise. This stackoverflow answer on subclassing list might be helpful to you.


To address your edit, a more general solution would be fairly simple - instead of overriding the __add__() function, try overriding __getitem__() , which is called whenever you use the square-bracket operators:

class CustomList(list):
    def __getitem__(self, y):
        if len(self) == 1:
            return self[0][y]
        else:
            return self[y]

This might cause problems when trying to concatenate arrays, however; list3 + list1 would cause an error because list1 was not an iterable, though of course you could override __add__ to simply add the second value as a list element if the list was more than one element long.


Console output using the above declaration:

>>> list1 = CustomList([2])
>>> list2 = CustomList([3])
>>> list3 = CustomList([4,5,6])
>>> print(list1 + list2)
5
>>> print(list2 + list3)
[3, 4, 5, 6]

Assuming by adding two classes you meant concatenating two lists, you could do something like this (notice the __add__ method to see how to addition works):

from collections import MutableSequence

class CustomList(MutableSequence):
    def __init__(self, data=[]):
        self._list = data 

    def __add__(self, newlist):
        return self._list + newlist._list

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

    def __getitem__(self, i):
        return self._list[i]

    def __delitem__(self, i):
        del self._list[i]

    def __setitem__(self, i, val):
        self._list[i] = val

    def __str__(self):
        return str(self._list)

    def insert(self, i, val):
        self._list.insert(i, val)

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