2009-12-05 14 views
3

我需要跟蹤Python中float和int值的單位,但我不想使用像幅度或其他值這樣的外部包,因爲我不需要對這些值執行操作。相反,我所需要的是能夠定義具有單位屬性的浮點數和整數(並且我不想爲這種簡單的事情添加新的依賴項)。我試着這樣做:單位的Python值

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? 

回答

8

你可能會尋找這樣的事情:

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 
+0

「寫下來,」國王對陪審團說,陪審團熱切地在他們的石板上寫下了三個日期,然後把它們加起來,減少先令和便士的答案。 - 愛麗絲夢遊仙境 - L.卡羅爾 – 2009-12-05 17:48:30

-2

它看起來像你需要檢查,如果kwargs不無你試試,看看是否有標籤「之前單元'。

更改您的代碼

if kwargs and 'unit' in kwargs: 

更新答案:

don't pass kwargs to __oldinit__ 
1

我想你的意思

class floatwithunit(float): 

而不是

def floatwithunit(float): 
+0

好點!我沒有看到 – 2009-12-05 17:00:01

+0

謝謝 - 我更新了問題,因爲我仍然有問題 – astrofrog 2009-12-05 17:06:05

6

您需要覆蓋__new__(「構造函數本身」,而__init__是「初始化程序」),否則float__new__會被無關參數調用,這是您看到的問題的原因。你不需要撥打浮動的__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

0

亞歷克斯·馬爾泰利確實指出了問題的根源。然而,我總是發現__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)