List of active deprecations#
This pages lists all active deprecations in the SymPy codebase. See the Deprecation Policy page for a description of SymPy’s deprecation policy, as well as instructions for contributors on how to deprecate things.
In particular, the deprecation policy for SymPy is for deprecations to last at least 1 year after the first major release that includes the deprecation. After that period, the deprecated functionality may be removed from SymPy, and code will need to be updated to use the replacement feature to continue working.
During the deprecation period, a SymPyDeprecationWarning
message will be
printed whenever the deprecated functionality is used. It is recommended for
users to update their code so that it does not use deprecated functionality,
as described below for each given deprecation.
Silencing SymPy Deprecation Warnings#
To silence SymPy deprecation warnings, add a filter using the
warnings
module. For
example:
import warnings
from sympy.utilities.exceptions import SymPyDeprecationWarning
warnings.filterwarnings(
# replace "ignore" with "error" to make the warning raise an exception.
# This useful if you want to test you aren't using deprecated code.
"ignore",
# message may be omitted to filter all SymPyDeprecationWarnings
message=r"(?s).*<regex matching the warning message>",
category=SymPyDeprecationWarning,
module=r"<regex matching your module>"
)
Here (?s).*<regex matching the warning message>
is a regular expression
matching the warning message. For example, to filter a warning about
sympy.printing
, you might use message=r"(?s).*sympy\.printing"
. The
leading (?s).*
is there because the warnings module matches message
against the start of the warning message, and because typical warning messages
span multiple lines.
<regex matching your module>
should be a regular expression matching your
module that uses the deprecated code. It is recommended to include this so
that you don’t also silence the same warning for unrelated modules.
This same pattern may be used to instead turn SymPyDeprecationWarning
into
an error so that you can test that you aren’t using deprecated code. To do
this, replace "ignore"
with "error"
in the above example. You may
also omit message
to make this apply to all SymPyDeprecationWarning
warnings.
If you are using pytest, you can use the pytest warnings filtering
capabilities
to either ignore SymPyDeprecationWarning
or turn them into errors.
Note
The Python -W
flag and
PYTHONWARNINGS
environment
variable
will NOT work to filter SymPy deprecation warnings (see this blog
post
by Ned Batchelder and this SymPy
issue for details on why). You
will need to either add a warnings
filter as above or use pytest to filter
SymPy deprecation warnings.
Version 1.11#
Mathematica parser: removed additional_translations
parameter#
The additional_translations
parameter for the Mathematica parser is now deprecated.
Additional translation rules to convert Mathematica expressions into SymPy ones
should be specified after the conversion using SymPy’s .replace( ) or .subs( )
methods on the output expression. If the translator fails to recognize the logical
meaning of a Mathematica expression, a form similar to Mathematica’s full form
will be returned, using SymPy’s Function
object to encode the nodes of the
syntax tree.
For example, suppose you want F
to be a function that returns the maximum
value multiplied by the minimum value, the previous way to
specify this conversion was:
>>> from sympy.parsing.mathematica import mathematica
>>> mathematica('F[7,5,3]', {'F[*x]':'Max(*x)*Min(*x)'})
21
Now you can do the same with
>>> from sympy import Function, Max, Min
>>> mathematica("F[7,5,3]").replace(Function("F"), lambda *x: Max(*x)*Min(*x))
21
Version 1.10#
Some traversal functions have been moved#
Some traversal functions have moved. Specifically, the functions
bottom_up
interactive_traversal
postorder_traversal
preorder_traversal
use
have moved to different SymPy submodules.
These functions should be used from the top-level sympy
namespace, like
sympy.preorder_traversal
or
from sympy import preorder_traversal
In general, end-users should use the top-level sympy
namespace for any
functions present there. If a name is in the top-level namespace, its specific
SymPy submodule should not be relied on, as functions may move around due to
internal refactorings.
sympy.core.trace
#
The trace object sympy.core.trace.Tr()
was moved to
sympy.physics.quantum.trace.Tr()
. This was because it was only used in the
sympy.physics.quantum
submodule, so it was better to have it there than in
the core.
The sympy.core.compatibility
submodule#
The sympy.core.compatibility
submodule is deprecated.
This submodule was only ever intended for internal use. Now that SymPy no longer supports Python 2, this module is no longer necessary, and the remaining helper functions have been moved to more convenient places in the SymPy codebase.
Some of the functions that were in this module are available from the top-level SymPy namespace, i.e.,
sympy.ordered
sympy.default_sort_key
or
from sympy import ordered, default_sort_key
In general, end-users should use the top-level sympy
namespace for any
functions present there. If a name is in the top-level namespace, its specific
SymPy submodule should not be relied on, as functions may move around due to
internal refactorings.
The remaining functions in sympy.core.compatibility
were only intended for
internal SymPy use and should not be used by user code.
Additionally, these two functions, ordered
and default_sort_key
, also used
to be in sympy.utilities.iterables
but have been moved from there as well.
Version 1.9#
expr_free_symbols
#
The expr_free_symbols
attribute of various SymPy objects is deprecated.
expr_free_symbols
was meant to represent indexed objects such as
MatrixElement
and Indexed
as free symbols. This was
intended to make derivatives of free symbols work. However, this now works
without making use of the method:
>>> from sympy import Indexed, MatrixSymbol, diff
>>> a = Indexed("A", 0)
>>> diff(a**2, a)
2*A[0]
>>> X = MatrixSymbol("X", 3, 3)
>>> diff(X[0, 0]**2, X[0, 0])
2*X[0, 0]
This was a general property that was added to solve a very specific problem but it added a layer of abstraction that is not necessary in general.
objects that have structural “non-expression” nodes already allow one to focus on the expression node if desired, e.g.
>>> from sympy import Derivative, symbols, Function >>> x = symbols('x') >>> f = Function('f') >>> Derivative(f(x), x).expr f(x)
introduction of this property encourages imprecise thinking when requesting free_symbols since it allows one to get symbols from a specific node of an object without specifying the node
the property was incorrectly added to
AtomicExpr
so numbers are returned asexpr_free_symbols
:>>> S(2).expr_free_symbols 2
the application of the concept was misapplied to define
Subs.expr_free_symbols
: it added inexpr_free_symbols
of the point but the point is aTuple
so nothing was addedit was not used anywhere else in the codebase except in the context of differentiating a
Subs
object, which suggested that it was not something of general use, this is also confirmed by the fact that,it was added without specific tests except for test of the derivatives of the Subs object for which it was introduced
See issue #21494 for more discussion.
sympy.stats.sample(numsamples=n)
#
The numsamples
parameter to sympy.stats.sample()
is deprecated.
numsamples
makes sample()
return a list of size numsamples
, like
>>> from sympy.stats import Die, sample
>>> X = Die('X', 6)
>>> sample(X, numsamples=3)
[3, 2, 3]
However, this functionality can be easily implemented by the user with a list comprehension
>>> [sample(X) for i in range(3)]
[5, 4, 3]
Additionally, it is redundant with the size
parameter, which makes sample
return a NumPy array with the given shape.
>>> sample(X, size=(3,))
array([6, 6, 1])
Historically, sample
was changed in SymPy 1.7 so it returned an iterator
instead of sample value. Since an iterator was returned, a numsamples
parameter was added to specify the length of the iterator.
However, this new behavior was considered confusing, as discussed in issue
#21563, so it was reverted.
Now, sample_iter
should be used if a iterator is needed. Consequently, the
numsamples
parameter is no longer needed for sample()
.
sympy.polys.solvers.RawMatrix
#
The RawMatrix
class is deprecated. The RawMatrix
class was a subclass
of Matrix
that used domain elements instead of Expr
as the elements of
the matrix. This breaks a key internal invariant of Matrix
and this kind
of subclassing limits improvements to the Matrix
class.
The only part of SymPy that documented the use of the RawMatrix
class was
the Smith normal form code, and that has now been changed to use
DomainMatrix
instead. It is recommended that anyone using RawMatrix
with
the previous Smith Normal Form code should switch to using DomainMatrix
as
shown in issue #21402. A better
API for the Smith normal form will be added later.
Non-Expr
objects in a Matrix#
In SymPy 1.8 and earlier versions it was possible to put non-Expr
elements in a Matrix
and the matrix elements could be any arbitrary
Python object:
>>> M = Matrix([[(1, 2), {}]])
This is not useful and does not really work, e.g.:
>>> M + M
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'Dict' and 'Dict'
The main reason for making this possible was that there were a number of
Matrix
subclasses in the SymPy codebase that wanted to work with objects
from the polys module, e.g.
RawMatrix
(see above) was used insolve_lin_sys
which was part ofheurisch
and was also used bysmith_normal_form
. TheNewMatrix
class used domain elements as the elements of the Matrix rather thanExpr
.NewMatrix
was used in theholonomic
module and also used domain elements as matrix elementsPolyMatrix
used a mix ofPoly
andExpr
as the matrix elements and was used byrisch
.
All of these matrix subclasses were broken in different ways and the
introduction of DomainMatrix
(#20780,
#20759,
#20621,
#19882,
#18844) provides a better
solution for all cases. Previous PRs have removed the dependence of these
other use cases on Matrix
(#21441,
#21427,
#21402) and now
#21496 has deprecated having
non-Expr
in a Matrix
.
This change makes it possible to improve the internals of the Matrix class but
it potentially impacts on some downstream use cases that might be similar to
the uses of Matrix
with non-Expr
elements that were in the SymPy codebase.
A potential replacement for code that used Matrix
with non-Expr
elements
is DomainMatrix
if the elements are something like domain elements
and a domain object can be provided for them. Alternatively if the goal is
just printing support then perhaps TableForm
can be used.
It isn’t clear what to advise as a replacement here without knowing more about the usecase. If you are unclear how to update your code, please open an issue or write to our mailing list so we can discuss it.
The get_segments
attribute of plotting objects#
The get_segments
method implemented in Line2DBaseSeries
is used
to convert two list of coordinates, x
and y
, into a list of segments used
by Matplotlib’s LineCollection
to plot a line.
Since the list of segments is only required by Matplotlib (for example, Bokeh,
Plotly, Mayavi, K3D only require lists of coordinates), this has been moved
inside the MatplotlibBackend
class.
Note that previously, the method
get_points()
always returned
uniformly sampled points, which meant that some functions were not plotted
correctly when using get_points()
to plot with Matplotlib.
To avoid this problem, the method get_segments()
could be used, which used
adaptive sampling and which could be used with Matplotlib’s LineCollection
.
However, this has been changed, and now get_points()
can also use adaptive
sampling. The get_data()
method can also be used.
The mdft
function in sympy.physics.matrices
#
The sympy.physics.matrices.mdft()
function is deprecated. It can be replaced
with the DFT
class in sympy.matrices.expressions.fourier
.
In particular, replace mdft(n)
with DFT(n).as_explicit()
. For example:
>>> from sympy.physics.matrices import mdft
>>> mdft(3) # DEPRECATED
Matrix([
[sqrt(3)/3, sqrt(3)/3, sqrt(3)/3],
[sqrt(3)/3, sqrt(3)*exp(-2*I*pi/3)/3, sqrt(3)*exp(2*I*pi/3)/3],
[sqrt(3)/3, sqrt(3)*exp(2*I*pi/3)/3, sqrt(3)*exp(-2*I*pi/3)/3]])
>>> from sympy.matrices.expressions.fourier import DFT
>>> DFT(3)
DFT(3)
>>> DFT(3).as_explicit()
Matrix([
[sqrt(3)/3, sqrt(3)/3, sqrt(3)/3],
[sqrt(3)/3, sqrt(3)*exp(-2*I*pi/3)/3, sqrt(3)*exp(2*I*pi/3)/3],
[sqrt(3)/3, sqrt(3)*exp(2*I*pi/3)/3, sqrt(3)*exp(-2*I*pi/3)/3]])
This was changed because the sympy.physics
submodule is supposed to only
contain things that are specific to physics, but the discrete Fourier
transform matrix is a more general mathematical concept, so it is better
located in the sympy.matrices
module. Furthermore, the DFT
class is a
matrix expression, meaning it can be unevaluated
and support symbolic shape.
The private SparseMatrix._smat
and DenseMatrix._mat
attributes#
The ._mat
attribute of Matrix
and the
._smat
attribute of SparseMatrix
are
deprecated.
The internal representation of Matrix
and SparseMatrix
was changed to be a
DomainMatrix
in #21626
so that it is no longer possible to expose a mutable list/dict as a way of
mutating a Matrix
. Instead of ._mat
the new .flat()
method can be used,
which returns a new list that cannot be used to mutate the Matrix
itself.
Instead of ._smat
the .todok()
method can be used which returns a new
dict.
Note that these attributes are already changed in SymPy 1.9 to return read-only copies, so that any code that relied on mutating them will be broken. Also these attributes were technically always private (they started with an underscore), so user code should not really have been using them in the first place.
laplace_transform of a Matrix with noconds=False#
Prior to version 1.9, calling laplace_transform()
on a Matrix
with
noconds=False
(which is the default), resulted in a Matrix of tuples:
>>> from sympy import laplace_transform, symbols, eye
>>> t, z = symbols('t z')
>>> laplace_transform(eye(2), t, z)
Matrix([
[(1/z, 0, True), (0, 0, True)],
[ (0, 0, True), (1/z, 0, True)]])
However, Matrix
is only designed to work with Expr
objects (see
Non-Expr objects in a Matrix above).
To avoid this, either use noconds=True
to remove the convergence conditions
>>> laplace_transform(eye(2), t, z, noconds=True)
Matrix([
[1/z, 0],
[ 0, 1/z]])
or use legacy_matrix=False
to return the new behavior, which will be to
return a single tuple with the Matrix in the first argument and the
convergence conditions combined into a single condition for the whole matrix.
>>> laplace_transform(eye(2), t, z, legacy_matrix=False)
(Matrix([
[1/z, 0],
[ 0, 1/z]]), 0, True)
When this deprecation is removed the legacy_matrix=False
behavior will
become the default, but the flag will be left intact for compatibility.
Version 1.8#
sympy.printing.theanocode
#
Theano has been discontinued, and forked
into a new project called Aesara. The
sympy.printing.theanocode
module has been renamed to
sympy.printing.aesaracode
, and all the corresponding functions have
been renamed (e.g., theano_code
has been renamed to aesara_code()
,
TheanoPrinter
has been renamed to AesaraPrinter
, and so on).
Version 1.7.1#
Calling sympy.stats.StochasticProcess.distribution
with RandomIndexedSymbol
#
The distribution
method of sympy.stats
stochastic
processes used to accept a
RandomIndexedSymbol
(that is, a stochastic process indexed with a
timestamp), but should now only be called with the timestamp.
For example, if you have
>>> from sympy import symbols
>>> from sympy.stats import WienerProcess
>>> W = WienerProcess('W')
>>> t = symbols('t', positive=True)
Previously this would work
W.distribution(W(t)) # DEPRECATED
It should now be called like
>>> W.distribution(t)
NormalDistribution(0, sqrt(t))
This was change was made as part of a change to store only Basic
objects in
sympy.stats
.args
. See issue
#20078 for details.
Version 1.7#
sympy.stats.DiscreteMarkovChain.absorbing_probabilites()
#
The absorbing_probabilites
method name was misspelled. The correct spelling
absorbing_probabilities()
(“absorbing probabilities”) should be used
instead.
sympy.utilities.misc.find_executable()
#
The function sympy.utilities.misc.find_executable()
is deprecated. Instead
use the standard library
shutil.which()
function, which has been in the standard library since Python 3.3 and is more
powerful.
Mutable attributes in sympy.diffgeom
#
Several parts of sympy.diffgeom
have been updated to no longer be
mutable, which better matches the immutable design used in the rest of SymPy.
Passing strings for symbol names in
CoordSystem
is deprecated. Instead you should be explicit and pass symbols with the appropiate assumptions, for instance, instead ofCoordSystem(name, patch, ['x', 'y']) # DEPRECATED
use
CoordSystem(name, patch, symbols('x y', real=True))
Similarly, the
names
keyword argument has been renamed tosymbols
, which should be a list of symbols.The
Manifold.patches
attribute is deprecated. Patches should be tracked separately.The
Patch.coord_systems
attribute is deprecated. Coordinate systems should be tracked separately.The
CoordSystem.transforms
attribute,CoordSystem.connect_to()
method, andCoordSystem.coord_tuple_transform_to()
method are deprecated. Instead, use therelations
keyword to theCoordSystem
class constructor and theCoordSystem.transformation()
andCoordSystem.transform()
methods (see the docstring ofCoordSystem
for examples).
The unicode
argument and attribute to sympy.printing.pretty.stringpict.prettyForm
and the sympy.printing.pretty.pretty_symbology.xstr
function#
The sympy.printing.pretty.pretty_symbology.xstr
function, and the unicode
argument and attribute to sympy.printing.pretty.stringpict.prettyForm
were both present to support the Unicode behavior of Python 2. Since Unicode
strings are the default in Python 3, these are not needed any more. xstr()
should be replaced with just str()
, the unicode
argument to prettyForm
should be omitted, and the prettyForm.unicode
attribute should be replaced
with the prettyForm.s
attribute.
The sympy.printing.fcode
, sympy.printing.ccode
, and sympy.printing.cxxcode
modules#
The submodules sympy.printing.ccode
, sympy.printing.fcode
, and
sympy.printing.cxxcode
were renamed to sympy.printing.c
,
sympy.printing.fortran
, and sympy.printing.cxx
, respectively.
These modules were renamed because they conflict with the corresponding
function names. This causes issues because from sympy.printing import ccode
can give the function or the module, depending on whether the ccode
submodule has been imported yet or not. See this comment on issue
#20234
for a technical discussion on why this happens.
Passing the arguments to lambdify
as a set
#
Passing the function arguments to lambdify as a set is deprecated. Instead pass them as a list or tuple. For example, instead of
lambdify({x, y}, x + 2*y) # WRONG
use
lambdify((x, y), x + 2*y) # RIGHT
This is because sets are unordered. For instance, in the above example it
would be impossible for lambidfy
to know if it was called with {x, y}
or
{y, x}
. Thus, when passed the arguments as a set lambdify
would have to
guess their order, which would lead to an incorrect function if it guessed
incorrectly.
Core operators no longer accept non-Expr args#
The core operator classes Add
, Mul
, and Pow
can no longer be constructed directly with objects that are not subclasses of
Expr
.
Expr
is the superclass of all SymPy classes that represent scalar
numeric quantities. For example, sin
, Symbol
, and
Add
are all subclasses of Expr
. However, may objects in
SymPy are not Expr
because they represent some other type of
mathematical object. For example, Set
, Poly
, and
Boolean
are all non-Expr
. These do not make mathematical sense
inside of Add
, Mul
, and Pow
, which are designed specifically to
represent the addition, multiplication, and exponentiation of scalar complex
numbers.
Manually constructing one of these classes with such an object is possible, but it will generally create something that will then break. For example
Mul(1, Tuple(2)) # This is deprecated
works and creates Tuple(2)
, but only because Mul
is “tricked” by always
treating \(1 \cdot x = x\). If instead you try
Mul(2, Tuple(2)) # This is deprecated
it fails with an exception
AttributeError: 'Tuple' object has no attribute 'as_coeff_Mul'
because it tries to call a method of Expr
on the Tuple
object, which does
not have all the Expr
methods (because it is not a subclass of Expr
).
If you want to use the +
, *
, or **
operation on a non-Expr
object, use
the operator directly rather than using Mul
, Add
or Pow
. If functional
versions of these are desired, you can use a lambda
or the
operator
module.
Version 1.6#
Various sympy.utilities
submodules have moved#
The following submodules have been renamed.
sympy.utilities.benchmarking
→sympy.testing.benchmarking
sympy.utilities.pytest
→sympy.testing.pytest
sympy.utilities.randtests
→sympy.core.random
sympy.utilities.runtests
→sympy.testing.runtests
sympy.utilities.tmpfiles
→sympy.testing.tmpfiles
sympy.testing.randtest
#
sympy.testing.randtest
is deprecated. The functions in it have been moved to
sympy.core.random
. The following functions have been moved.
sympy.testing.randtest.random_complex_number
→sympy.core.random.random_complex_number
sympy.testing.randtest.verify_numerically
sympy.core.random.verify_numerically
sympy.testing.randtest.test_derivative_numerically
→sympy.core.random.test_derivative_numerically
sympy.testing.randtest._randrange
→sympy.core.random._randrange
sympy.testing.randtest._randint
→sympy.core.random._randint
Mixing Poly
and non-polynomial expressions in binary operations#
In previous versions of SymPy, Poly
was a subclass of
Expr
, but it has been changed to only be a subclass of
Basic
. This means that some things that used to work with Poly
are now deprecated because they are only designed to work with Expr
objects.
This includes combining Poly
with Expr
objects using binary operations,
for example
Poly(x)*sin(x) # DEPRECATED
To do this, either explicitly convert the non-Poly
operand to a Poly
using
Expr.as_poly()
or convert the Poly
operand to an Expr
using Poly.as_expr()
, depending on which type you want the result to
be.
The print_cyclic
flag of sympy.combinatorics.Permutation
#
The print_cyclic
attribute of
sympy.combintorics.Permutation
controls whether permutations print as cycles or arrays. This would be done by
setting Permutation.print_cyclic = True
or Permutation.print_cyclic = False
. However, this method of controlling printing is bad because it is a
global flag, but printing should not depend on global behavior.
Instead, users should use the perm_cyclic
flag of the corresponding printer.
The easiest way to configure this is to set the flag when calling
init_printing()
, like
>>> from sympy import init_printing
>>> init_printing(perm_cyclic=False) # Makes Permutation print in array form
>>> from sympy.combinatorics import Permutation
>>> Permutation(1, 2)(3, 4)
⎛0 1 2 3 4⎞
⎝0 2 1 4 3⎠
The Permutation
docstring contains more details on the
perm_cyclic
flag.
Using integrate
with Poly
#
In previous versions of SymPy, Poly
was a subclass of
Expr
, but it has been changed to only be a subclass of
Basic
. This means that some things that used to work with Poly
are now deprecated because they are only designed to work with Expr
objects.
This includes calling integrate()
or Integral
with Poly
.
To integrate a Poly
, use the Poly.integrate()
method. To compute the
integral as an Expr
object, call the Poly.as_expr()
method
first.
See also Mixing Poly and non-polynomial expressions in binary operations above.
The string fallback in sympify()
#
The current behavior of sympify()
is that sympify(expr)
tries
various methods to try to convert expr
into a SymPy objects. If all these
methods fail, it takes str(expr)
and tries to parse it using
parse_expr()
. This string fallback feature is deprecated. It is
problematic for a few reasons:
It can affect performance in major ways. See for instance issues #18056 and #15416 where it caused up to 100x slowdowns. The issue is that SymPy functions automatically call
sympify
on their arguments. Whenever a function is passed something thatsympify
doesn’t know how to convert to a SymPy object, for instance, a Python function type, it passes the string toparse_expr()
. This is significantly slower than the direct conversions that happen by default. This occurs specifically wheneversympify()
is used in library code instead of_sympify()
(or equivalentlysympify(strict=True)
), but presently this is done a lot. Usingstrict=True
will at some point be the default for all library code, but this is a harder change to make.It can cause security issues, since strings are evaled, and objects can return whatever string they want in their
__repr__
. See also https://github.com/sympy/sympy/pull/12524.It really isn’t very useful to begin with. Just because an object’s string form can be parsed into a SymPy expression doesn’t mean it should be parsed that way. This is usually correct for custom numeric types, but an object’s repr could be anything. For instance, if the string form of an object looks like a valid Python identifier, it will parse as a
Symbol
.
There are plenty of ways to make custom objects work inside of
sympify()
.
Firstly, if an object is intended to work alongside other SymPy expressions, it should subclass from
Basic
(orExpr
). If it does,sympify()
will just return it unchanged because it will already be a valid SymPy object.For objects that you control, you can add the
_sympy_
method. The sympify docstring has an example of this.For objects that you don’t control, you can add a custom converter to the
sympy.core.sympify.converter
dictionary. Thesympify()
docstring also has an example of this.
To silence this deprecation warning in all cases, you can pass strict=True
to sympify()
. However, note that this will also disable some other
conversions such as conversion of strings (for converting strings to SymPy
types, you can explicitly use parse_expr()
).
Creating an indefinite Integral
with an Eq
argument#
Passing an Eq()
object to
integrate()
is deprecated in the case where the integral is
indefinite. This is because if \(f(x) = g(x)\), then \(\int f(x)\,dx = \int
g(x)\,dx\) is not true in general, due to the arbitrary constants (which
integrate
does not include).
If you want to make an equality of indefinite integrals, use
Eq(integrate(f(x), x), integrate(g(x), x))
explicitly.
If you already have an equality object eq
, you can use Eq(integrate(eq.lhs, x), integrate(eq.rhs, x))
.
Version 1.5#
Tensor.fun_eval
and Tensor.__call__
#
TensExpr.fun_eval
and Tensor.__call__
(i.e., calling a tensor to evaluate
it) are deprecated. The Tensor.substitute_indices()
method should be used.
This was changed because fun_eval
was considered a confusing name and using
function evaluation was considered both confusing and dangerous.
TensorType
#
The TensorType
class is deprecated. Use tensor_heads()
instead. The
TensorType
class had no purpose except shorter creation of
TensorHead
objects.
See also The tensorhead() function below.
The dummy_fmt
argument to TensorIndexType
#
The dummy_fmt
keyword argument to TensorIndexType
is deprecated.
Setting dummy_fmt='L'
leads to _dummy_fmt='L_%d'
, which is confusing and
uses obsolete string formatting. dummy_name
should be used instead. This
change was made because dummy_name
is a clearer name.
The metric
argument to TensorIndexType
#
The metric
keyword argument to TensorIndexType
is deprecated.
The name “metric” was ambiguous because it meant “metric symmetry” in some
places and “metric tensor” in others.
Either the metric_symmetry
keyword or the TensorIndexType.set_metric()
method should be used instead.
The get_kronecker_delta()
and get_epsilon()
methods of TensorIndexType
#
The get_kronecker_delta()
and get_epsilon()
methods of
TensorIndexType
are deprecated. Use the TensorIndexType.delta
and
TensorIndexType.epsilon
properties instead, respectively.
The tensorsymmetry()
function#
The tensorsymmetry()
function in sympy.tensor
is deprecated. Use the
TensorSymmetry
class constructor instead.
TensorSymmetry
is preferred over tensorsymmetry()
because the latter
Does not have any extra functionality
Involves obscure Young tableau
Is not a member of the
TensorSymmetry
class
The tensorhead()
function#
The tensorhead()
function is deprecated in favor of tensor_heads()
.
tensor_heads()
is more consistent with other SymPy names (i.e., Symbol
and
symbols()
or TensorIndex
and tensor_indices()
). It also does not use
Young tableau to denote symmetries.
Methods to sympy.physics.units.Quantity
#
The following methods of
sympy.physics.units.quantities.Quantity
are deprecated.
Quantity.set_dimension()
. This should be replaced withunit_system.set_quantity_dimension
orQuantity.set_global_dimension()
.Quantity.set_scale_factor()
. This should be replaced withunit_system.set_quantity_scale_factor
orQuantity.set_global_relative_scale_factor()
Quantity.get_dimensional_expr()
. This is now associated withUnitSystem
objects. The dimensional relations depend on the unit system used. Useunit_system.get_dimensional_expr()
instead.Quantity._collect_factor_and_dimension
. This has been moved to theUnitSystem
class. Useunit_system._collect_factor_and_dimension(expr)
instead.
See The dimension and scale_factor arguments to sympy.physics.units.Quanitity below for the motivation for this change.
The is_EmptySet
attribute of sets#
The is_EmptySet
attribute of Set objects is deprecated.
Instead either use
from sympy import S
s is S.EmptySet
or
s.is_empty
The difference is that s.is_empty
may return None
if it is unknown if the
set is empty.
ProductSet(iterable)
#
Passing a single iterable as the first argument to ProductSet
is
deprecated. Creating a product set from an iterable should be done using
ProductSet(*iterable)
, or as each individual argument. For example
>>> from sympy import ProductSet
>>> sets = [{i} for i in range(3)]
>>> ProductSet(*sets)
ProductSet({0}, {1}, {2})
>>> ProductSet({1, 2}, {1})
ProductSet({1, 2}, {1})
This is done because sets themselves can be iterables, and sets of sets are
allowed. But the product set of a single set should mathematically be that set
itself (or more exactly, the set of 1-tuples of elements of that set).
Automatically denesting a single iterable makes it impossible to represent
this object and makes ProductSet
not generalize correctly when passed 1
argument. On the other hand, treating the first argument differently if it is
a set than if it is another type of iterable (which is what is currently done
in the deprecated code path) is confusing behavior.
The set_potential_energy
method in sympy.physics.mechanics
#
The set_potential_energy()
methods of sympy.physics.mechanics.particle.Particle
and sympy.physics.mechanics.rigidbody.RigidBody
are deprecated.
Instead one should set the Particle.potential_energy
and
RigidBody.potential_energy
attributes to set the potential energy,
like
P.potential_energy = scalar
This change was made to be more Pythonic, by using setters and getters of a
@property
method rather than an explicit set_
method.
Using a set for the condition in ConditionSet
#
Using a set for the condition in ConditionSet is deprecated. A boolean should be used instead. This is because the condition is mathematically a boolean, and it is ambiguous what a set should mean in this context.
To fix this deprecation, replace
ConditionSet(symbol, set_condition)
with
ConditionSet(symbol, And(*[Eq(lhs, 0) for lhs in set_condition]))
For example,
ConditionSet((x, y), {x + 1, x + y}, S.Reals) # DEPRECATED
would become
ConditionSet((x, y), Eq(x + 1, 0) & Eq(x + y, 0), S.Reals)
The max_degree
and get_upper_degree
properties of sympy.polys.multivariate_resultants.DixonResultant
#
The max_degree
property and get_upper_degree()
methods of DixonResultant
are deprecated. See issue #17749
for details.
Eq(expr)
with the rhs defaulting to 0#
Calling Eq
with a single argument is
deprecated. This caused the right-hand side to default to 0
, but this
behavior was confusing. You should explicitly use Eq(expr, 0)
instead.
Non-tuple iterable for the first argument to Lambda
#
Using a non-tuple as the first argument to Lambda
is deprecated. If
you have a non-tuple, convert it to a tuple first, like Lambda(tuple(args), expr)
.
This was done so that Lambda
could support general tuple unpacking, like
>>> from sympy import Lambda, symbols
>>> x, y, z = symbols('x y z')
>>> f = Lambda((x, (y, z)), x + y + z)
>>> f(1, (2, 3))
6
The evaluate
flag to differentiate_finite
#
The evaluate
flag to differentiate_finite()
is deprecated.
differentiate_finite(expr, x, evaluate=True)
expands the intermediate
derivatives before computing differences. But this usually not what you want,
as it does not satisfy the product rule.
If you really do want this behavior, you can emulate it with
diff(expr, x).replace(
lambda arg: arg.is_Derivative,
lambda arg: arg.as_finite_difference())
See the discussion on issue #17881.
Version 1.4#
The clear_cache
and clear_subproducts
keywords to Matrix.is_diagonalizable
#
The clear_cache
and clear_subproducts
keywords to
Matrix.is_diagonalizable()
are deprecated. These used to clear cached entries, but this cache was removed
because it was not actually safe given that Matrix
is mutable. The keywords
now do nothing.
The rows
and cols
keyword arguments to Matrix.jordan_block
#
The rows
and cols
keywords to
Matrix.jordan_block
are
deprecated. The size
parameter should be used to specify the (square) number
of rows and columns.
The non-square matrices created by setting rows
and cols
are not
mathematically Jordan block matrices, which only make sense as square
matrices.
To emulate the deprecated jordan_block(rows=n, cols=m)
behavior, use a
general banded matrix constructor, like
>>> from sympy import Matrix, symbols
>>> eigenvalue = symbols('x')
>>> def entry(i, j):
... if i == j:
... return eigenvalue
... elif i + 1 == j: # use j + 1 == i for band='lower'
... return 1
... return 0
>>> # the same as the deprecated Matrix.jordan_block(rows=3, cols=5, eigenvalue=x)
>>> Matrix(3, 5, entry)
Matrix([
[x, 1, 0, 0, 0],
[0, x, 1, 0, 0],
[0, 0, x, 1, 0]])
Version 1.3#
The source()
function#
The source()
function is deprecated. Use
inspect.getsource(obj)
instead, or if you are in IPython or Jupyter, use obj??
.
The dimension
and scale_factor
arguments to sympy.physics.units.Quanitity
#
The dimension
and scale_factor
arguments to
sympy.physics.units.quantities.Quantity
are deprecated.
The problem with these arguments is that dimensions are not an absolute association to a quantity. For example:
in natural units length and time are the same dimension (so you can sum meters and seconds).
SI and cgs units have different dimensions for the same quantities.
At this point a problem arises for scale factor as well: while it is always
true that kilometer / meter == 1000
, some other quantities may have a
relative scale factor or not depending on which unit system is currently being
used.
Instead, things should be managed on the DimensionSystem
class. The
DimensionSystem.set_quantity_dimension()
method should be used instead of the
dimension
argument, and the
DimensionSystem.set_quantity_scale_factor()
method should be used
instead of the scale_factor
argument.
See issue #14318 for more details. See also Methods to sympy.physics.units.Quantity above.
Importing classof
and a2idx
from sympy.matrices.matrices
#
The functions sympy.matrices.matrices.classof
and
sympy.matrices.matrices.a2idx
were duplicates of the same functions in
sympy.matrices.common
. The two functions should be used from the
sympy.matrices.common
module instead.
Version 1.2#
Dot product of non-row/column vectors#
The Matrix.dot()
method has
confusing behavior where A.dot(B)
returns a list corresponding to
flatten(A.T*B.T)
when A
and B
are matrices that are not vectors (i.e.,
neither dimension is size 1). This is confusing. The purpose of Matrix.dot()
is to perform a mathematical dot product, which should only be defined for
vectors (i.e., either a \(n\times 1\) or \(1\times n\) matrix), but in a way that
works regardless of whether each argument is a row or column vector.
Furthermore, returning a list here was much less useful than a matrix would
be, and resulted in a polymorphic return type depending on the shapes of the
inputs.
This behavior is deprecated. Matrix.dot
should only be used to do a
mathematical dot product, which operates on row or column vectors. Use the
*
or @
operators to do matrix multiplication.
>>> from sympy import Matrix
>>> A = Matrix([[1, 2], [3, 4]])
>>> B = Matrix([[2, 3], [1, 2]])
>>> A*B
Matrix([
[ 4, 7],
[10, 17]])
>>> A@B
Matrix([
[ 4, 7],
[10, 17]])
sympy.geometry.Line3D.equation
no longer needs the k
argument#
The k
argument to sympy.geometry.line.Line3D.equation()
method is
deprecated.
Previously, the function Line3D.equation
returned (X, Y, Z, k)
which was
changed to (Y-X, Z-X)
(here X
, Y
and Z
are expressions of x
, y
and
z
respectively). As in 2D an equation is returned relating x
and y
just
like that in 3D two equations will be returned relating x
, y
and z
.
So in the new Line3D.equation
the k
argument is not needed anymore. Now
the k
argument is effectively ignored. A k
variable is temporarily formed
inside equation()
and then gets substituted using subs()
in terms of x
and then (Y-X, Z-X)
is returned.
Previously:
>>> from sympy import Point3D,Line3D
>>> p1,p2 = Point3D(1, 2, 3), Point3D(5, 6, 7)
>>> l = Line3D(p1, p2)
>>> l.equation()
(x/4 - 1/4, y/4 - 1/2, z/4 - 3/4, k)
Now:
>>> from sympy import Point3D, Line3D, solve
>>> p1,p2 = Point3D(1, 2, 3), Point3D(5, 6, 7)
>>> l = Line3D(p1,p2)
>>> l.equation()
(-x + y - 1, -x + z - 2)