Пример наследования в Python - PullRequest
1 голос
/ 07 июля 2010

Мне не понятно, как задать этот вопрос. Если бы я это сделал, я, вероятно, был бы намного ближе к решению ... Мне нужно немного понять наследство.

Я хочу создать пользовательский подтип 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 ]

5 голосов
/ 07 июля 2010
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 голос
/ 07 июля 2010

Вот несколько способов заставить ваши тестовые случаи проходить

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

, очевидно, вы должны также реализовать __add__, __mul__ и т. Д. *

Сказав, что- каков ваш вариант использования?Это кажется странной вещью, которую хочется сделать

1 голос
/ 07 июля 2010

То, что вы хотите сделать, на самом деле очень сложно. Я не знаю ни одного программного обеспечения Python, которое подклассов типа, например float или int, а затем делает математику с ним. Я думаю, что, возможно, есть лучший способ достичь того, чего вы пытаетесь достичь, без использования подкласса float. Вы должны исследовать альтернативы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...