我在使用内置类型的派生类编写简单的单位转换器时遇到了一些困难float
。
尝试 1:我尝试返回实例的新副本,而不是
change the state of it
. 但是,我无法做到这一点。attempl 2 我尝试更改 的值
self
,但它破坏了属性baseunit
,所以AttributeError
提出了。
另一件事是我真正想知道的是如何在不丢失类类型的情况下实现代数,例如a = Unit(km/s, 1) * 10
返回 Unit 的实例print a # 10 km/s
而不是 float 10.0
。所以我可以使用 进一步转换它a.to('m/s')
,然后print a # 1e4 m/s
谢谢我提前!
编辑
我根据您的建议修改了我的代码,并正确使用了new。它部分有效,因为我可以获得类 Unit 的转换实例并将其传递给变量。这有点够了。但是,有没有一种方法可以在现场进行更改,即让返回的实例替换我原来的实例?
再说一次,如果我尝试以另一种方式开展业务,即
self /= self.conv[target]
self.baseunit = target
它抛出 AttributeError 因为self
now 只是一个普通的浮点数。我想我应该定义一个覆盖代数运算符的函数,这样baseunit
就不会丢失。但是如何?
代码:
from __future__ import division
import numpy as np
class Unit(float):
"""provide a simple unit converter for a given quantity"""
baseconv = {'length': np.array((1e-10, 1e-6, 1e-2, 1., 1e3),
dtype=[('A', 'f'),
('um', 'f'),
('cm', 'f'),
('m', 'f'),
('km','f')]),
'speed': np.array((1e3, 1., 1e-2, 1e-10,),
dtype=[('km/s', 'f'),
('m/s', 'f'),
('cm/s', 'f'),
('A/s', 'f')]),
'1': np.array((1.,), dtype=[('1','f')])}
baseunit = None
def __new__(self, baseunit='1',num=1.):
return super(Unit,self).__new__(self, num)
def __init__(self, baseunit='1', num=1.):
"""set up base unit"""
self.baseunit = baseunit
for _key,_val in self.baseconv.items():
if baseunit in _val.dtype.names:
utype = _key
break
else:
raise TypeError('Unit not defined: {:s}'.format(baseunit))
self.conv = np.array(tuple(np.array(self.baseconv[utype].tolist())
/ self.baseconv[utype][baseunit]),
dtype=self.baseconv[utype].dtype)
def __str__(self,):
return '{:e} {:s}'.format(self, self.baseunit)
def to(self,target):
if target in self.conv.dtype.names:
return Unit(target, self / self.conv[target]) ! not work
else:
raise TypeError('Invalid converter: {:s}->{:s}'
.format(self.baseunit, target))
if __name__=='__main__':
u_test = Unit('km/s')
print u_test # 1.0000 km/s
u_conv = u_test.to('cm/s')
print u_conv # 1e5 cm/s
print u_test # 1.000 km/s