【问题标题】:Extending base classes in Python在 Python 中扩展基类
【发布时间】:2010-09-07 04:57:11
【问题描述】:

我正在尝试在 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 方法中的局部变量,但这阻止我修改分配给实例的初始值班级。

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

【问题讨论】:

    标签: python


    【解决方案1】:

    您的两个 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】:

      int 是一个值类型,所以每次你做一个赋值,(例如上面+= 的两个实例),它不会修改你在堆上的对象,而是用其中一个替换引用赋值右侧的结果(即int

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

      此页面有更多关于差异的详细信息:The Python Language Reference - 3. Data model

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

      【讨论】:

      • Python 没有“值类型”和引用类型。可变类型和不可变类型之间的区别只是有点相似,并不是基于这种区别。不过,您建议使用组合而不是继承非常好。
      【解决方案3】:

      我稍微扩展了你的 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】:

        Ints 是不可变的,你不能就地修改它们,所以你应该使用选项 #2(因为选项 #1 是不可能的,没有一些技巧)。

        【讨论】:

          【解决方案5】:

          我写了一个可变整数类的例子,它实现了来自the list of operator methods 的一些基本方法。它可以正确打印、加减乘除、排序和比较相等性。

          如果你想让它做 int 所能做的所有事情,你就必须实现更多的方法。

          class MutablePartialInt:
              def __init__(self, value):
                  self.value = value
          
              def _do_relational_method(self, other, method_to_run):
                  func = getattr(self.value, method_to_run)
                  if type(other) is MutablePartialInt:
                      return func(other.value)
                  else:
                      return func(other)
          
              def __add__(self, other):
                  return self._do_relational_method(other, "__add__")
              
              def __sub__(self, other):
                  return self._do_relational_method(other, "__sub__")
          
              def __mul__(self, other):
                  return self._do_relational_method(other, "__mul__")
              
              def __truediv__(self, other):
                  return self._do_relational_method(other, "__truediv__")
          
              def __floordiv__(self, other):
                  return self._do_relational_method(other, "__floordiv__")
          
              def __eq__(self, other):
                 return self._do_relational_method(other, "__eq__")
              
              def __neq__(self, other):
                 return self._do_relational_method(other, "__neq__")
          
              def __lt__(self, other):
                  return self._do_relational_method(other, "__lt__")
          
              def __gt__(self, other):
                  return self._do_relational_method(other, "__gt__")
          
              def __str__(self):
                  return str(self.value)
          
              def __repr__(self):
                  return self.__str__()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-07-13
            • 2021-12-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-27
            相关资源
            最近更新 更多