Я пытаюсь расширить некоторые «базовые» классы в 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 метод Добавить не изменяет значение внешней переменной Икс. Я полагаю, что это нормально в том смысле, что себя является локальной переменной в методе Добавить класса, но это не позволяет мне изменить начальное значение, присвоенное экземпляру класса.
Можно ли таким образом расширить класс или я должен определить свойство класса с базовым типом и сопоставить все необходимые методы с этим свойством?






Инты неизменяемы, и вы не можете изменять их на месте, поэтому вам следует выбрать вариант №2 (поскольку вариант №1 невозможен без некоторых уловок).
int - это тип значения, поэтому каждый раз, когда вы выполняете присвоение (например, оба экземпляра + = выше), он не изменяет объект, который у вас есть в куче, а заменяет ссылку одним из результатов правой стороны присвоения (т.е. int)
список не является типом значения, поэтому он не связан теми же правилами.
эта страница содержит более подробную информацию о различиях: http://docs.python.org/ref/objects.html
ИМО, да, вы должны определить новый класс, который сохраняет int как переменную экземпляра
Ваши два примера 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)
Python не имеет «типов значений» и ссылочных типов. Различие между изменяемыми и неизменяемыми типами лишь отчасти похоже и не основано на таком различии. Тем не менее, ваша рекомендация использовать композицию вместо наследования прекрасна.