Расширение базовых классов в Python

Я пытаюсь расширить некоторые «базовые» классы в Python:

class xlist (list):
    def len(self):
        return len(self)

    def add(self, *args):
        self.extend(args)
        return None


class xint (int):
    def add(self, value):
        self += value
        return self


x = xlist([1,2,3])
print x.len()   ## >>> 3 ok
print x         ## >>> [1,2,3] ok
x.add (4, 5, 6)
print x         ## >>> [1,2,3,4,5,6] ok

x = xint(10)
print x         ## >>> 10 ok
x.add (2)
print x         ## >>> 10  # Not ok (#1)

print type(x)         ## >>> <class '__main__.xint'> ok
x += 5
print type(x)         ## >>> <type 'int'>  # Not ok (#2)

Он отлично работает в случае список, потому что метод добавить изменяет объект «на месте», не возвращая его. Но в случае int метод Добавить не изменяет значение внешней переменной Икс. Я полагаю, что это нормально в том смысле, что себя является локальной переменной в методе Добавить класса, но это не позволяет мне изменить начальное значение, присвоенное экземпляру класса.

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
12
0
20 968
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Инты неизменяемы, и вы не можете изменять их на месте, поэтому вам следует выбрать вариант №2 (поскольку вариант №1 невозможен без некоторых уловок).

Ответ принят как подходящий

int - это тип значения, поэтому каждый раз, когда вы выполняете присвоение (например, оба экземпляра + = выше), он не изменяет объект, который у вас есть в куче, а заменяет ссылку одним из результатов правой стороны присвоения (т.е. int)

список не является типом значения, поэтому он не связан теми же правилами.

эта страница содержит более подробную информацию о различиях: http://docs.python.org/ref/objects.html

ИМО, да, вы должны определить новый класс, который сохраняет int как переменную экземпляра

Python не имеет «типов значений» и ссылочных типов. Различие между изменяемыми и неизменяемыми типами лишь отчасти похоже и не основано на таком различии. Тем не менее, ваша рекомендация использовать композицию вместо наследования прекрасна.

Mike Graham 24.04.2010 22:35

Ваши два примера xint не работают по двум разным причинам.

Первый не работает, потому что self += value эквивалентен self = self + value, который просто переназначает локальную переменную self на другой объект (целое число), но не меняет исходный объект. Вы действительно не можете этого понять

>>> x = xint(10)
>>> x.add(2)

для работы с подклассом int, поскольку целые числа - неизменный.

Чтобы второй заработал, вы можете определить __add__ метод, например:

class xint(int):
    def __add__(self, value):
        return xint(int.__add__(self, value))

>>> x = xint(10)
>>> type(x)
<class '__main__.xint'>
>>> x += 3
>>> x
13
>>> type(x)
<class '__main__.xint'>

Я немного расширил ваш класс xlist, сделал его так, чтобы вы могли найти все индексные точки числа, сделав его так, чтобы вы могли расширять его сразу несколькими списками, инициализировав его и сделав так, чтобы вы могли его перебирать

class xlist:
    def __init__(self,alist):
        if type(alist)==type(' '):
            self.alist = [int(i) for i in alist.split(' ')]
        else:
            self.alist = alist
    def __iter__(self):
        i = 0
        while i<len(self.alist):
            yield self.alist[i]
            i+=1
    def len(self):
        return len(self.alist)
    def add(self, *args):
        if type(args[0])==type([1]):
            if len(args)>1:
                tmp = []
                [tmp.extend(i) for i in args]
                args = tmp
            else:args = args[0]
        if type(args)==type(''):args = [int(i) for i in args.split(' ')] 
        (self.alist).extend(args)
        return None
    def index(self,val):
        gen = (i for i,x in enumerate(self.alist) if x == val)
        return list(gen)

Другие вопросы по теме