2008-08-28 5 views
10

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

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

ответ

5

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

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

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

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

+4

Python не имеет «типов значений» и ссылочных типов. Различие между изменяемыми и неизменяемыми типами несколько схоже и не основано на таком различии. Однако ваша рекомендация использовать композицию вместо наследования велика. – 2010-04-24 18:35:59

0

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

23

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

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

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

работать с подклассом int, так как целые числа immutable.

Чтобы получить вторую для работы вы можете определить __add__ method, например, так:

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'> 
2

я расширил вы 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) 
Смежные вопросы