On Mon, Jun 29, 2020 at 2:43 PM David Bailey <[email protected]> wrote:
>
> On 29/06/2020 17:16, Oscar Benjamin wrote:
>
>
> In any significant codebase star-import is a bad idea. It makes it
> hard to trace the origin of an imported name when looking at the code.
> If I'm looking at the code and I see sp.cos then I expect that sp will
> be defined or imported somewhere at the top of the file and I can just
> go to the first occurrence of it in the file to see where it comes
> from. Likewise if you use "from sympy import cos" and I see cos(2) I
> expect that cos will be imported at the top and I can search for that.
>
> I feel there are some good reasons to star import SymPy (which is why this 
> subject keeps coming up) these reasons tend to get downplayed. One is the 
> obvious fact that complicated algebraic equations just don't look nice with 
> sp. prefixing functions like cos(). Another is the fact that I would guess 
> many users only intend to use SymPy even though their code is complicated - 
> not really throw away one-off code. Such users are, in effect, using Sympy as 
> an algebra processing system, and are not interested in Python, though they 
> might want to import their own modules that also star imported SymPy.
>
> SymPy's 750000 lines of code is obviously an extreme case.
>
> There also seems to be a certain inconsistency associated with importing 
> SymPy symbols selectively (tested using 1.6):
>
> import sympy
> from sympy import integrate
> from sympy import sin
> x=sympy.symbols('x')
>
> integrate(sin(x),x)
>
> Returns
>
> -cos(x)
>
> I would have expected -sympy.cos(x), and indeed if you subsequently enter 
> cos(x), you get a name error because cos is not defined!

The printer doesn't take into account your namespace. It is
copy-pastable from the point of view of having all the SymPy names
imported. We could add a string printer mode that prefixes all SymPy
names.

>
>
> For these reasons, I think it might be worth devising a set of rules that can 
> be followed so as to import SymPy safely as widely as possible. How about:
>
> 1)          Only import SymPy  using  * Thus numpy (say) would have to be 
> imported as
>
> import numpy as np and incur the clumsier syntax of np.cos(...)
>
> This is nearly inevitable because you can't end up with two things called cos.

If you are writing code in a file, import * should be avoided. This
applies to all modules, not just SymPy. There are many issues with it.

- It makes it hard for both human readers and linters to detect if a
name is undefined or mispelled. For example, pyflakes completely gives
up on trying to find undefined names if there is an import *.
- If you combine multiple import *s, the actual name that gets
imported is whichever was imported last. It can be difficult to tell
this if you don't know for sure *every* name that is included in an
import *.
- If a module isn't careful about defining __all__, import * may
import more than you would expect. SymPy as of recent versions defines
__all__ but it didn't used to. And many other libraries do not. For
example, say a module has "import sys" in its __init__.py and you do
an import * of that module. Then you would get "sys" defined even
though you never ran "import sys". Even worse things are possible here
too, such as an import * overriding a built-in name. SymPy does try to
avoid this, but other packages are not as careful.

import * is just fine for interactive use, although the caveats about
SymPy and NumPy including the same names still apply. The issue is
that for .py files, import * starts to lead to code smells that can
give you issues down the line making the code both harder to read and
maintain. Remember that if you are putting your code in a file, then
your goal is to make that code readable by other people (even if
"other people" just means your future self).

If you don't like using sym.cos and so on everywhere, you can just
import things directly, like

from sympy import cos

That is just fine. If you look at the code in SymPy itself, it uses
this pattern (except it often imports directly from submodules, which
end-users should not do). For example, look at the test_solvers.py
file 
https://github.com/sympy/sympy/blob/master/sympy/solvers/tests/test_solvers.py.
There are a lot of imports there, but it is not a problem. You could
also use a tool like isort to keep the imports clean and in order.
Also tools like pyflakes make it easy to keep track of which names you
have forgotten to import, or which imports are no longer necessary.

The only issue with doing a direct import like this is that if you are
also using a library like NumPy, you need to be careful because NumPy
also has a cos() function, and it is incompatible with SymPy's. If
your code is primarily SymPy code that uses NumPy only in a small
part, you could do

from sympy import cos, ...
import numpy as np

and use the np.cos prefix in the parts where you need the NumPy
version. It all really depends on what your code is doing and what
will make it the most readable.

Aaron Meurer

>
> 2)         If you are importing other modules that you have written, use 
> exactly the same import commands in all of them.
>
> Struggling as a newcomer with SymPy without importing everything including 
> sympy.abc (and maybe without knowing the Python language) can be extremely 
> frustrating .
>
> David
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/b0324ab9-fe2c-e813-9c95-04a0c6864a96%40dbailey.co.uk.

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAKgW%3D6%2B7qThpU4Q-mPBUSwyhx%2BYoSHC%3DAA4-3fsxMd%2BeOsiFBg%40mail.gmail.com.

Reply via email to