Python:对于在超类中定义的操作符,我可以有一个子类返回它自己类型的实例吗?

2024-04-19 20:36:18 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python(2.7)中,我想创建一个有理数类,它模仿Fraction类的行为(在模块分数中),但是覆盖了urepr_uu方法,以匹配uu str_uu的结果。最初的想法只是为了我自己的修补,只是为了让闲置的输出看起来更友好。但是现在我更感兴趣的是理解底层的继承/类型问题——我认为这可能是大家感兴趣的——而不是为这个特定的用例找到一个变通方法,这显然是微不足道的。在

问题是,我也希望继承所有数值运算符的功能(方法是add_优,uu sub_u,等等),但是结果是我的子类的实例,而不是分数。这正是我想要的,但事实是这样的:

class Q(Fraction):
    def __repr__(self):
        return str(self)

>>> Q(1,2)
1/2
>>> Q(1,2) + Q(1,3)
Fraction(5, 6)

这是因为在分数中定义的运算符返回分数实例。当然,我可以单独地重写所有这些神奇的方法,调用父类进行计算,然后强制使用我的类型,但是我觉得应该有一种方法来处理这种重复的情况(即不需要编写“def”20次)。在

我还考虑过使用\uGetAttribute_Uu来拦截方法调用,但这看起来不优雅,非常脆弱,而且在比这个稍微复杂的情况下几乎肯定会失败。(我知道首选的方法是使用getattr,但似乎无法捕捉到我感兴趣的方法调用,因为它们是在基类中定义的!)在

既然我不是基类的作者,有没有比单独重写每个方法更好的方法呢?在


Tags: 模块实例方法self类型定义def情况
1条回答
网友
1楼 · 发布于 2024-04-19 20:36:18

这需要一点工作,但您可以包装它并创建一个委托人。实际上,我做了一些类似于您所做的事情,创建一个默认情况下以十六进制打印的int。我自己的一个类中有一个更好的例子,它将int类化,以允许位切片读取(显然写不起作用,因为int是不可变的,所以这个特定的代码没有走多远…)。例如,可能有很多代码,但它展示了如何使用它:

# I stole this decorator from another stackoverflow recipe :) 
def returnthisclassfrom(specials):
  specialnames = ['__%s__' % s for s in specials.split()]
  def wrapit(cls, method):
    return lambda *a: cls(method(*a))
  def dowrap(cls):
    for n in specialnames:
      method = getattr(cls, n)
      setattr(cls, n, wrapit(cls, method))
    return cls
  return dowrap

def int_getslice(self, i, j):
    # NON-pythonic, will return everything inclusive i.e. x[5:3] returns 3 bits, not 2.
    # Because that's what users normally expect.
    # If you're a purist, modify below.
    if i > 1000000 or j > 1000000:
        raise ValueError, 'BitSize limited to 1 million bits'
    lo = min(i,j)
    hi = max(i,j)
    mask = (1<<((hi-lo)+1))-1

    return (self>>lo) & mask

def int_getitem(self, i):
    # Safety limit
    if i > 1000000:
        raise ValueError, 'BitSize limited to 1 million bits'
    return (self>>i)&1

def int_iter(self):
    # since getitem makes it iterable, override
    raise AttributeError, 'int object is not iterable'

@returnthisclassfrom('abs add and div floordiv lshift mod mul neg or pow radd rand rdiv rdivmod rfloordiv rlshift rmod rmul ror rpow rrshift rshift rsub rxor rtruediv sub truediv xor trunc')
class BitSliceInt(long):
  __getslice__ = int_getslice
  __getitem__ = int_getitem
  __iter__ = int_iter

相关问题 更多 >