1234567891011121314151617181920212223242526272829class xlist list:
def lenself:
return lenself def addself, *arg"/>

在Python中扩展基类

在Python中扩展基类

Extending base classes in Python

我正在尝试扩展Python中的一些"基础"类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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方法中的局部变量的意义上讲,这很好,但是这使我无法修改分配给该类实例的初始值。

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


您的两个xint示例由于两个不同的原因而无法工作。

第一个无效,因为self += value等效于self = self + value,后者只是将局部变量self重新分配给另一个对象(整数),但不会更改原始对象。你真的不能得到这个

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

int的子类一起使用,因为整数是不可变的。

要使第二个方法起作用,您可以定义一个__add__方法,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
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'>


int是一个值类型,因此每次执行赋值时(例如,=的两个实例),它都不会修改您在堆上拥有的对象,而是将引用替换为赋值的右侧(即int)

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

此页面提供了有关差异的更多详细信息:http://docs.python.org/ref/objects.html

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


我稍微扩展了xlist类,使其成为一个整数,以便可以找到一个数字的所有索引点,从而可以一次扩展多个列表,从而对其进行初始化和迭代,从而可以遍历它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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)

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


推荐阅读