Python中的继承示例

时间:2010-07-07 05:00:16

标签: python inheritance

我不清楚如何提出这个问题。如果我这样做,我可能会更接近解决方案..我需要对继承有所了解。

我想制作float的自定义子类型。但我希望在执行任何常规float方法(__add____mul__等)之前,此子类型的实例重新计算其值。在这个例子中,它应该将其值乘以全局因子:

class FactorFloat(float):
    # I don't think I want to do this:
    ##    def __new__(self, value):
    ##        return float.__new__(self, value)
    def __init__(self, value):
        float.__init__(self, value)
    # Something important is missing..
    # I want to do something with global FACTOR
    # when any float method is called.

f = FactorFloat(3.)
FACTOR = 10.
print f   # 30.0
print f-1 # 29.0
FACTOR = 2.
print f   # 6.0
print f-1 # 5.0

这是一个只是一个消毒的例子,我认为我的观点得到了解决。如有必要,我会发布更复杂的“真实”问题。

3 个答案:

答案 0 :(得分:5)

class FactorFloat(float):
    def _factor_scale(f):
        def wrapper(self, *args, **kwargs):
            scaled = float.__mul__(self, FACTOR)
            result = f(scaled, *args, **kwargs)
            # if you want to return FactorFloats when possible:
            if isinstance(result, float):
                result = type(self)(result/FACTOR)
            return result
        return wrapper

    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, float.__repr__(self))

    __str__ = _factor_scale(float.__str__)
    __mul__ = _factor_scale(float.__mul__)
    __div__ = _factor_scale(float.__div__)
    __add__ = _factor_scale(float.__add__)
    __sub__ = _factor_scale(float.__sub__)


f = FactorFloat(3.)
FACTOR = 10.
print f   # 30.0
print f-1 # 29.0
FACTOR = 2.
print f   # 6.0
print f-1 # 5.0
print repr(f)

有:

30.0
29.0
6.0
5.0
FactorFloat(3.0)

修改

回应评论中的问题;使用类装饰器使事情略微更加通用和自动化。我不会循环dir(baseclass),而是明确列出我希望包装的方法。在下面的示例中,我将它们列在类变量_scale_methods中。

def wrap_scale_methods(cls):
    Base = cls.__base__
    def factor_scale(f):
        def wrapper(self, *args, **kwargs):
            scaled = Base.__mul__(self, FACTOR)
            result = f(scaled, *args, **kwargs)
            if isinstance(result, Base):
                result = type(self)(result/FACTOR)
            return result
        return wrapper
    for methodname in cls._scale_methods:
        setattr(cls, methodname, factor_scale(getattr(Base, methodname)))
    return cls

@wrap_scale_methods
class FactorComplex(complex):
    _scale_methods = '__str__ __mul__ __div__ __add__ __sub__'.split()
    def __repr__(self):
        return '%s(%s)' % (type(self).__name__, complex.__repr__(self)[1:-1])

答案 1 :(得分:1)

你想要做的事实上很难。我不知道任何python软件是一个类型的子类,如floatint,然后用它做数学。我认为,如果不使用float的子类,也许有更好的方法可以实现您想要实现的目标。你应该研究替代方案。

答案 2 :(得分:1)

以下是一些让您的测试用例通过的方法

def __str__(self):
    return str(FACTOR*self)
def __sub__(self, other):
    return self*FACTOR-other

显然你还必须实施__add____mul__等......

说完了 - 你的用例是什么?这似乎是一件奇怪的事情