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

Python中的继承示例

  •  1
  • Paul  · 技术社区  · 15 年前

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

    我想创建的自定义子类型 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 回复  |  直到 14 年前
        1
  •  5
  •   Matt Anderson    15 年前
    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])
    
        2
  •  1
  •   Jerub    15 年前

    你想做的其实很难。我不知道有什么python软件可以对一个类型进行子类化,比如 float int 然后用它来做数学。我认为,也许有更好的方法来完成你正在尝试实现的目标,而不使用 浮动 . 你应该研究替代方案。

        3
  •  1
  •   John La Rooy    15 年前

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

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

    显然,您还必须实现 __add__ , __mul__ 等。

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