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.
