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

在Python中扩展基类

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

    我试图在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)
    

    它在 列表 案件,因为 附加 方法“就地”修改对象,但不返回它 国际性组织 案例,the 添加 方法不修改外部的值 英语字母表的第24个字母 变量。从某种意义上说,我想这很好 自己 是中的局部变量 添加 类的方法,但这阻止了我修改分配给类实例的初始值。

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

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

    你的两个 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
  •  23
  •   dF.    17 年前

    int 是一种值类型,因此每次执行赋值操作时(例如 += 上面),它不会修改堆上的对象,而是将引用替换为赋值右侧的结果之一(即 国际性组织 )

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

    本页详细介绍了这些差异: The Python Language Reference - 3. Data model

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

        3
  •  2
  •   gtmanfred    14 年前

    我稍微扩展了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    17 年前

    Int是不可变的,你不能在原地修改它们,所以你应该选择选项#2(因为如果没有一些技巧,选项#1是不可能的)。