summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHernan Grecco <hernan.grecco@gmail.com>2014-10-19 13:26:55 -0300
committerHernan Grecco <hernan.grecco@gmail.com>2014-10-19 13:26:55 -0300
commit2f2166aa9d492473d5aa134e0d70e58857260f2f (patch)
treeed092e30864f107b0ec5619868b99a0fda0fd657
parent15d2ff3e2176e45721d2bcb4a7e8bd1d7254efee (diff)
parentce681a4ba59c8d50da09db07c5ee286542bfbef6 (diff)
downloadpint-2f2166aa9d492473d5aa134e0d70e58857260f2f.tar.gz
Merge branch 'MatthieuDartiailh-speedups' into develop
-rw-r--r--pint/unit.py54
1 files changed, 33 insertions, 21 deletions
diff --git a/pint/unit.py b/pint/unit.py
index 95af3be..51ecef6 100644
--- a/pint/unit.py
+++ b/pint/unit.py
@@ -257,7 +257,7 @@ class Definition(object):
def _is_dim(name):
- return name.startswith('[') and name.endswith(']')
+ return name[0] == '[' and name[-1] == ']'
class PrefixDefinition(Definition):
@@ -509,6 +509,9 @@ class UnitRegistry(object):
#: Maps dimensionality (_freeze(UnitsContainer)) to Units (_freeze(UnitsContainer))
self._dimensionality_cache = TransformDict(_freeze)
+ #: Cache the unit name associated to user input. ('mV' -> 'millivolt')
+ self._parse_unit_cache = dict()
+
#: When performing a multiplication of units, interpret
#: non-multiplicative units as their *delta* counterparts.
self.default_as_delta = default_as_delta
@@ -841,7 +844,7 @@ class UnitRegistry(object):
return ''
try:
- return self._units[name_or_alias].name
+ return self._units[name_or_alias]._name
except KeyError:
pass
@@ -898,7 +901,7 @@ class UnitRegistry(object):
if input_units in self._dimensionality_cache:
return copy.copy(self._dimensionality_cache[input_units])
- accumulator = defaultdict(lambda: 0.0)
+ accumulator = defaultdict(float)
self._get_dimensionality_recurse(input_units, 1.0, accumulator)
dims = UnitsContainer(dict((k, v) for k, v in accumulator.items() if v != 0.))
@@ -906,20 +909,22 @@ class UnitRegistry(object):
if '[]' in dims:
del dims['[]']
+ self._dimensionality_cache[input_units] = copy.copy(dims)
+
return dims
def _get_dimensionality_recurse(self, ref, exp, accumulator):
- for key, value in ref.items():
- exp2 = exp*value
+ for key in ref:
+ exp2 = exp*ref[key]
if _is_dim(key):
reg = self._dimensions[key]
if reg.is_base:
accumulator[key] += exp2
- elif reg.reference != None:
+ elif reg.reference is not None:
self._get_dimensionality_recurse(reg.reference, exp2, accumulator)
else:
reg = self._units[self.get_name(key)]
- if reg.reference != None:
+ if reg.reference is not None:
self._get_dimensionality_recurse(reg.reference, exp2, accumulator)
def get_base_units(self, input_units, check_nonmult=True):
@@ -944,7 +949,7 @@ class UnitRegistry(object):
if check_nonmult and input_units in self._base_units_cache:
return copy.deepcopy(self._base_units_cache[input_units])
- accumulators = [1., defaultdict(lambda: 0.0)]
+ accumulators = [1., defaultdict(float)]
self._get_base_units(input_units, 1.0, accumulators)
factor = accumulators[0]
@@ -953,21 +958,21 @@ class UnitRegistry(object):
# Check if any of the final units is non multiplicative and return None instead.
if check_nonmult:
for unit in units.keys():
- if not isinstance(self._units[unit].converter, ScaleConverter):
+ if not self._units[unit].converter.is_multiplicative:
return None, units
return factor, units
def _get_base_units(self, ref, exp, accumulators):
- for key, value in ref.items():
+ for key in ref:
+ exp2 = exp*ref[key]
key = self.get_name(key)
reg = self._units[key]
- exp2 = exp*value
if reg.is_base:
accumulators[1][key] += exp2
else:
- accumulators[0] *= reg.converter.scale ** exp2
- if reg.reference != None:
+ accumulators[0] *= reg._converter.scale ** exp2
+ if reg.reference is not None:
self._get_base_units(reg.reference, exp2, accumulators)
def get_compatible_units(self, input_units):
@@ -1137,9 +1142,10 @@ class UnitRegistry(object):
"""Parse a unit to identify prefix, unit name and suffix
by walking the list of prefix and suffix.
"""
-
- for suffix, prefix in itertools.product(self._suffixes.keys(), self._prefixes.keys()):
- if unit_name.startswith(prefix) and unit_name.endswith(suffix):
+ stw = unit_name.startswith
+ edw = unit_name.endswith
+ for suffix, prefix in itertools.product(self._suffixes, self._prefixes):
+ if stw(prefix) and edw(suffix):
name = unit_name[len(prefix):]
if suffix:
name = name[:-len(suffix)]
@@ -1147,13 +1153,13 @@ class UnitRegistry(object):
continue
if case_sensitive:
if name in self._units:
- yield (self._prefixes[prefix].name,
- self._units[name].name,
+ yield (self._prefixes[prefix]._name,
+ self._units[name]._name,
self._suffixes[suffix])
else:
for real_name in self._units_casei.get(name.lower(), ()):
- yield (self._prefixes[prefix].name,
- self._units[real_name].name,
+ yield (self._prefixes[prefix]._name,
+ self._units[real_name]._name,
self._suffixes[suffix])
def parse_units(self, input_string, as_delta=None):
@@ -1169,6 +1175,9 @@ class UnitRegistry(object):
:class:`pint.UndefinedUnitError` if a unit is not in the registry
:class:`ValueError` if the expression is invalid.
"""
+ if input_string in self._parse_unit_cache:
+ return self._parse_unit_cache[input_string]
+
if as_delta is None:
as_delta = self.default_as_delta
@@ -1181,8 +1190,9 @@ class UnitRegistry(object):
ret = UnitsContainer()
many = len(units) > 1
- for name, value in units.items():
+ for name in units:
cname = self.get_name(name)
+ value = units[name]
if not cname:
continue
if as_delta and (many or (not many and value != 1)):
@@ -1191,6 +1201,8 @@ class UnitRegistry(object):
cname = 'delta_' + cname
ret[cname] = value
+ self._parse_unit_cache[input_string] = ret
+
return ret
def parse_expression(self, input_string, case_sensitive=True, **values):