Значения Python с единицами измерения - PullRequest
3 голосов
/ 05 декабря 2009

Мне нужно отслеживать единицы измерения в значениях типа float и int в Python, но я не хочу использовать внешний пакет, например, magnitude или другие, потому что мне не нужно выполнять операции со значениями. Вместо этого все, что я хочу - это иметь возможность определять числа с плавающей запятой и целые числа, которые имеют атрибут unit (и я не хочу добавлять новую зависимость для чего-то такого простого). Я пытался сделать:

class floatwithunit(float):

    __oldinit__ = float.__init__

    def __init__(self, *args, **kwargs):
        if 'unit' in kwargs:
            self.unit = kwargs.pop('unit')
        self.__oldinit__(*args, **kwargs)

Но это совсем не работает:

In [37]: a = floatwithunit(1.,unit=1.)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/Users/tom/<ipython console> in <module>()

TypeError: float() takes at most 1 argument (2 given)

Any suggestions?

Ответы [ 5 ]

8 голосов
/ 05 декабря 2009

Возможно, вы ищете что-то вроде этого:

class UnitFloat(float):

    def __new__(self, value, unit=None):
       return float.__new__(self, value)

    def __init__(self, value, unit=None):
        self.unit = unit


x = UnitFloat(35.5, "cm")
y = UnitFloat(42.5)

print x
print x.unit

print y
print y.unit

print x + y

Урожайность:

35.5
cm
42.5
None
78.0
6 голосов
/ 05 декабря 2009

Вам необходимо переопределить __new__ («собственно конструктор», в то время как __init__ - «инициализатор»), в противном случае float __new__ вызывается с посторонними аргументами, что является причиной проблемы ты видишь. Вам не нужно называть float __init__ (это неоперация). Вот как я это закодировал бы:

class floatwithunit(float):

    def __new__(cls, value, *a, **k):
        return float.__new__(cls, value)

    def __init__(self, value, *args, **kwargs):
        self.unit = kwargs.pop('unit', None)

    def __str__(self):
        return '%f*%s' % (self, self.unit)

a = floatwithunit(1.,unit=1.)

print a

испуская 1.000000*1.0.

1 голос
/ 05 декабря 2009

Я думаю, что вы имеете в виду

class floatwithunit(float):

вместо

def floatwithunit(float):
0 голосов
/ 05 декабря 2009

Алекс Мартелли действительно указал на корень проблемы. Однако я всегда нахожу __new__ весьма запутанным, поэтому вот рабочий пример кода:

class FloatWithUnit(float):
    def __new__(cls, *args, **kwargs):
        # avoid error in float.__new__
        # the original kwargs (with 'unit') will still be passed to __init__
        if 'unit' in kwargs:
            kwargs.pop('unit')
        return super(FloatWithUnit, cls).__new__(cls, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        self.unit = kwargs.pop('unit') if 'unit' in kwargs else None
        super(FloatWithUnit, self).__init__(*args, **kwargs)
0 голосов
/ 05 декабря 2009

Похоже, вам нужно проверить, не равен ли kwargs None, прежде чем пытаться увидеть, есть ли метка 'unit'.

Измените свой код на

 if kwargs and 'unit' in kwargs:

Обновленный ответ:

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