Рассматривать один элемент списка как скаляр в Python - PullRequest
0 голосов
/ 13 ноября 2018

possible Можно ли определить подкласс списка Python, который позволяет использовать одноэлементные переменные списка, как если бы они были скалярами?

Например, я хотел бы иметь возможность сделать:

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

, но сохраняя возможность использовать список как обычно:

for i in list3:
    print list[i]

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Предполагая, что, добавляя два класса, вы подразумевали объединение двух списков, вы можете сделать что-то вроде этого (обратите внимание на метод __add__, чтобы увидеть, как работает сложение):

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)
0 голосов
/ 13 ноября 2018

Да, но вам фактически потребуется переопределить любые методы, с которыми вы хотите, чтобы он работал.

Когда вы вызываете определенные операторы для таких объектов, как списки, вы в конечном итоге вызываете скрытые методы для этих объектов.В приведенном вами примере result = list1 + list2 фактически вызывается функция list1.__add__(list2).Вы можете создать подкласс list и переопределить эти методы, если хотите.Например:

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))

будет обрабатывать list1 и list2 как скаляры, если они оба имеют длину 1, и в противном случае будет ссылаться на обычную функциональность list. Этот ответ о переполнении стека при использовании подкласса list может быть полезен для вас.


Для решения проблемы редактирования более общее решение будет довольно простым - вместо переопределения __add__()функция, попробуйте переопределить __getitem__(), который вызывается всякий раз, когда вы используете операторы в квадратных скобках:

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

Однако это может вызвать проблемы при попытке объединить массивы;list3 + list1 может вызвать ошибку, поскольку list1 не является итеративным, хотя, конечно, вы можете переопределить __add__, просто добавив второе значение в качестве элемента списка, если список имеет длину более одного элемента.


Вывод на консоль с использованием вышеуказанного объявления:

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