在Python中扩展基类

时间:2008-08-28 22:18:03

标签: 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)

它在 list 的情况下工作正常,因为 append 方法“就地”修改了对象,而没有返回它。但在 int 情况下, add 方法不会修改外部 x 变量的值。我认为 self 是类的 add 方法中的局部变量,这是好的,但这阻止我修改分配给实例的初始值上课。

是否可以通过这种方式扩展类,还是应该使用基类型定义类属性并将所有需要的方法映射到此属性?

4 个答案:

答案 0 :(得分: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'>

答案 1 :(得分:5)

int 是一种值类型,因此每次执行赋值时(例如,上面的 + = 的两个实例),它都不会修改您拥有的对象在堆上,但用赋值右边的结果之一替换引用(即int)

列表不是值类型,因此不受相同规则的约束。

此页面详细介绍了差异:http://docs.python.org/ref/objects.html

IMO,是的,你应该定义一个新的类,它将int保存为实例变量

答案 2 :(得分: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)

答案 3 :(得分:0)

Int是不可变的,你不能在适当的位置修改它们,所以你应该使用选项#2(因为没有一些技巧就不可能选择#1)。