代码之家  ›  专栏  ›  技术社区  ›  PabloG

在python中扩展基类

  •  11
  • PabloG  · 技术社区  · 16 年前

    我尝试在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 案例 添加 方法不修改外部的值 X 变量。我想从这个意义上说没关系 自己 是中的局部变量 添加 方法,但这会阻止我修改分配给类实例的初始值。

    是否可以这样扩展类,或者应该用基类型定义类属性并将所有需要的方法映射到此属性?

    4 回复  |  直到 13 年前
        1
  •  5
  •   John Douthat    16 年前

    int 是值类型,因此每次执行赋值时(例如 += 上面),它不会修改堆中的对象,而是将引用替换为赋值右侧的一个结果(即int)。

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

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

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

        2
  •  23
  •   dF.    16 年前

    你们两个 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'>
    
        3
  •  2
  •   gtmanfred    13 年前

    我将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)
    
        4
  •  0
  •   dwestbrook    16 年前

    ints是不可变的,您不能在适当的地方修改它们,所以您应该使用选项2(因为如果没有一些技巧,选项1是不可能的)。