# HG changeset patch
# User "Lance Larsen <
lance.c...@gmail.com>"
# Date 1226946818 25200
# Node ID 060b92b72467a29a2d098e7ce0ee96cbf4c2395b
# Parent d1019a5c66d12d524fe64359c1bd8054cab0cfa9
Substitution syntax extension - implements f.subs(x=1,y=2) and
shorthand syntax f(x=1,y=2).
diff -r d1019a5c66d1 -r 060b92b72467 sympy/core/basic.py
--- a/sympy/core/basic.py Tue Nov 18 17:36:24 2008 +0100
+++ b/sympy/core/basic.py Mon Nov 17 11:33:38 2008 -0700
@@ -896,26 +896,43 @@
"""
return self
- def subs(self, *args):
+ def subs(self, *args, **kwargs):
"""
Substitutes an expression.
Calls either _subs_old_new, _subs_dict or _subs_list
depending
- if you give it two arguments (old, new), a dictionary or a
list.
+ if you give it two arguments (old, new), a dictionary, a list
or
+ pass in named parameters. When named parameters are passed
in,
+ these are converted to a dictionary and _subs_dict is called.
Examples:
>>> from sympy import *
>>> x,y = symbols('xy')
- >>> (1+x*y).subs(x, pi)
- 1 + pi*y
+ >>> (1+x*y).subs(x=pi, y=2)
+ 1 + 2*pi
>>> (1+x*y).subs({x:pi, y:2})
1 + 2*pi
>>> (1+x*y).subs([(x,pi), (y,2)])
1 + 2*pi
+ >>> (1+x*y).subs(x, pi)
+ 1 + pi*y
+
+ Subs can be called implicitly as well as shown in the
following
+ examples:
+
+ >>> f = 1+x*y
+ >>> f(x=pi, y=2)
+ 1 + 2*pi
+ >>> f({x:pi, y:2})
+ 1 + 2*pi
+ >>> f([(x,pi), (y,2)])
+ 1 + 2*pi
+ >>> f(x, pi)
+ 1 + pi*y
"""
- if len(args) == 1:
+ if len(args) == 1 and len(kwargs) == 0:
sequence = args[0]
if isinstance(sequence, dict):
return self._subs_dict(sequence)
@@ -923,9 +940,11 @@
return self._subs_list(sequence)
else:
raise TypeError("Not an iterable container")
- elif len(args) == 2:
+ elif len(args) == 2 and len(kwargs) == 0:
old, new = args
return self._subs_old_new(old, new)
+ elif len(args) == 0 and len(kwargs) > 0:
+ return self._subs_dict(kwargs)
else:
raise Exception("subs accept either 1 or 2 arguments")
@@ -1932,9 +1951,25 @@
from sympy.integrals import integrate
return integrate(self, *args, **kwargs)
- #XXX fix the removeme
- def __call__(self, *args, **removeme):
- return Function(self[0])(*args)
+ def __call__(self, *args, **kwargs):
+ """Alias for calling the subs function. All subs syntax is
supported
+ the two parameter syntax f(x,2) for f(x=2).
+
+ Examples:
+
+ >>> from sympy import *
+ >>> x,y = symbols('xy')
+ >>> f = 1+x*y
+ >>> f(x=pi,y=2)
+ 1 + 2*pi
+ >>> f({x:pi, y:2})
+ 1 + 2*pi
+ >>> f([(x,pi),(y,2)])
+ 1 + 2*pi
+ """
+ if len(args) > 1:
+ raise Exception("Unsupported syntax. Pass a dictionary, a
list of substitution pairs, or name=value pairs.")
+ return self.subs(*args, **kwargs)
def __float__(self):
result = self.evalf()
diff -r d1019a5c66d1 -r 060b92b72467 sympy/core/tests/test_subs.py
--- a/sympy/core/tests/test_subs.py Tue Nov 18 17:36:24 2008 +0100
+++ b/sympy/core/tests/test_subs.py Mon Nov 17 11:33:38 2008 -0700
@@ -169,3 +169,16 @@
assert (f(x,y)).subs(f,sin) == f(x,y)
assert (sin(x)+atan2(x,y)).subs([[atan2,f],[sin,g]]) == f(x,y) + g
(x)
assert (g(f(x+y, x))).subs([[f, l], [g, exp]]) == exp(x + sin(x +
y))
+
+def test_subs_call_syntax():
+ a, b, x, y, p, q = map(Symbol, "abxypq")
+ f = 2*a*x+3*b*y
+ assert f(x=1, y=2) == 2*a + 6*b
+ assert f({a*x:p,b*y:q}) == 2*p + 3*q
+
+def test_implicit_subs_call_syntax():
+ a, b, x, y, p, q = map(Symbol, 'abxypq')
+ f = 2*a*x + 3*b*y
+ assert f(x=1, y=2) == 2*a + 6*b
+ assert f({a*x:p,b*y:q}) == 2*p + 3*q
+ assert f([(a*x,p),(b*y,q)]) == 2*p + 3*q