在Python中扩展基类

时间:2020-03-05 18:44:44  来源:igfitidea点击:

我正在尝试扩展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)

在列表的情况下,它可以正常工作,因为append方法修改了"就地"对象,而不返回它。但是在int情况下,add方法不会修改外部x变量的值。我认为从self是该类的add方法中的局部变量的意义上讲,这很好,但是这使我无法修改分配给该类实例的初始值。

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

解决方案

回答

整数是不可变的,我们不能就地对其进行修改,因此我们应该使用选项#2(因为如果没有一些技巧,选项1是不可能的)。

回答

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

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

此页面上有更多区别的详细信息:http://docs.python.org/ref/objects.html

IMO,是的,我们应该定义一个新类,将一个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'>