From 96fa8130e88beaae339dbdea3bef8bf30f427767 Mon Sep 17 00:00:00 2001 From: Valentin Boettcher Date: Mon, 13 May 2019 09:54:19 +0200 Subject: [PATCH] add default arguments --- Readme.md | 20 ++++++++++++++++++++ SecondaryValue/SecondaryValue.py | 27 ++++++++++++++++++++++++--- setup.py | 2 +- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index c7cf3a4..c50fbb9 100644 --- a/Readme.md +++ b/Readme.md @@ -30,6 +30,26 @@ result = x(a=(1, 20), b=(2, 30), c=2) print(result) # >> array([ 1.41421356, 35.35533906]) +# As a goodie, you can print out the gaussian error distribution in +# symbolic form. (Works best in Jupyter Notebooks) +x.pretty_gauss_propagation('a', 'b', 'c') +``` + +### Default Values +To reduce boylerplate one can set default substitutions for symbols. +This especially usefull for constants. + +```python +from SecondaryValue import SecondaryValue + +# create a secondary value with default arguments +x = SecondaryValue("a + b", defaults=dict(b=1/2)) + +# this works because `b` is substituted from the defaults +result = x(b=1/2) +print(result) +# >> 1.0 + # As a goodie, you can print out the gaussian error distribution in # symbolic form. (Works best in Jupyter Notebooks) x.pretty_gauss_propagation('a', 'b', 'c') diff --git a/SecondaryValue/SecondaryValue.py b/SecondaryValue/SecondaryValue.py index 28c01a7..3fac247 100644 --- a/SecondaryValue/SecondaryValue.py +++ b/SecondaryValue/SecondaryValue.py @@ -14,28 +14,32 @@ class SecondaryValue: """ A value computed from a formular, optionally with error propagation. """ - def __init__(self, expr, dependencies=False, dtype=np.float64): + def __init__(self, expr, dependencies=False, defaults=False, + dtype=np.float64): """Creates a new Secondary Value. :param str expr: the expression from which to calculate the value, may be a sympy expression or a string. :param dict dependencies: secondary values to calculate as dependencies (in order) + :param dict defaults: Default arguments for the call. :param np.dtype dtype: the numpy datatype for the resulting value + """ self._expr = expr self._parsed = sympify(self._expr) if isinstance(self._expr, str) \ else self._expr - self._symbols = set([symbol.__str__() \ - for symbol in self._parsed.free_symbols]) + self._symbols = {symbol.__str__() \ + for symbol in self._parsed.free_symbols} self._deps = {name: dependency \ for name, dependency in dependencies.items() \ if name in self._symbols} if dependencies else {} + self._defaults = defaults self._dtype = dtype # with per-instance cache @@ -64,6 +68,22 @@ class SecondaryValue: return kwargs, calc_deps + def _inject_defaults(self, **kwargs): + """Injects the default value for arguments. + + :returns: the modified argument dictionary + :rtype: dict + """ + + if not self._defaults: + return kwargs + + for name, value in self._defaults.items(): + if name not in kwargs: + kwargs[name] = value + + return kwargs + def __call__(self, *args, **kwargs): """Calculates a value from the expression by substituting variables by the values of the given keyword arguments. If an @@ -78,6 +98,7 @@ class SecondaryValue: """ kwargs, dep_values = self._calc_deps(**kwargs) + kwargs = self._inject_defaults(**kwargs) # check for missing symbols if not self._symbols <= set(kwargs.keys()): diff --git a/setup.py b/setup.py index 39b66f7..b03dfc0 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ def readme(): return f.read() setup(name='SecondaryValue', - version='0.0.5', + version='0.0.6', description='A helper to calculate the gaussian error propagation.', long_description=readme(), long_description_content_type='text/markdown',