加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Python:我可以为超类中定义的运算符提供自己类型的子类吗?

发布时间:2020-12-20 13:38:20 所属栏目:Python 来源:网络整理
导读:在 Python(2.7)中,我想创建一个有理数的类,它模仿Fraction类的行为(在模块分数中),但是重写__repr__方法以匹配__str__的结果.最初的想法只是为了我自己的修补,只是为了让IDLE输出看起来更友好.但是现在我更感兴趣的是理解潜在的继承/打字问题 – 我认为这可
在 Python(2.7)中,我想创建一个有理数的类,它模仿Fraction类的行为(在模块分数中),但是重写__repr__方法以匹配__str__的结果.最初的想法只是为了我自己的修补,只是为了让IDLE输出看起来更友好.但是现在我更感兴趣的是理解潜在的继承/打字问题 – 我认为这可能是普遍感兴趣的 – 而不是为这个特定的用例找到一个解决方法,这无疑是微不足道的.

问题是,我想继承所有数值运算符(方法__add __,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ @这就是我想要的,但相反,这种情况发生了:

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

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

发生这种情况是因为Fraction中定义的运算符返回Fraction实例.当然,我可以单独覆盖所有这些魔术方法,调用父类进行数学计算然后强制转换为我的类型,但我觉得应该有办法一般地处理这种重复的情况(即不写“def”20次).

我还考虑使用__getattribute__来拦截方法调用,但这看起来不够优雅,非常脆弱,并且几乎可以保证在比这个更复杂的情况下失败. (我知道__getattr__是首选,但似乎不会捕获我感兴趣的方法调用,因为它们是在基类中定义的!)

鉴于我不是基类的作者,有没有比单独覆盖每个方法更好的方法?

解决方法

它有点工作,但你可以包装它并创建一个委托人.我实际上做了类似于你所做的事情,创建一个默认情况下会以十六进制打印的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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读