On Sat, Sep 05, 2020 at 04:00:40PM +0900, Stephen J. Turnbull wrote:
> Jeffrey Kintscher writes:
> 
>  > "from foo import *" is a really lazy programming practice
> 
> However much corporate policies and educators may deprecate widely
> adopted coding practices, complaining about them will get you
> disliked, and nothing else.

*scratches head in confusion*

Since when did `from foo import *` suddenly become a widely adopted 
coding practice?

Everyone I know agrees that (with very few exceptions) we should avoid 
star imports. I don't know anyone who argues in favour of star imports 
in the general case. It is permitted, but not encouraged.

PEP 8 strongly discourages it:

https://www.python.org/dev/peps/pep-0008/#imports

Google bans it, allowing only imports of modules:

https://github.com/google/styleguide/blob/gh-pages/pyguide.md

(Some conditions apply, but nothing that would allow wildcard imports.)

Linters warn about it:

https://www.flake8rules.com/rules/F403.html

The community seems to be in agreement that, for the most part, wildcard 
imports should be avoided, e.g.

https://www.geeksforgeeks.org/why-import-star-in-python-is-a-bad-idea/

https://stackoverflow.com/questions/2386714/why-is-import-bad

https://medium.com/@s16h/importing-star-in-python-88fe9e8bd4d2


and people have written tools to replace them:

https://www.asmeurer.com/removestar/


Of course it is right and proper that people should be permitted to use 
wildcard imports. Consenting Adults applies.

But I am perplexed that people seem to be arguing that we can't add new 
names to modules because that would break code that does a wildcard 
import from that module. When did that become a thing?

I'm perplexed because, firstly, we have never guaranteed that modules 
won't add new names to their namespace. *Removing* names is a backwards- 
incompatible change. *Adding* names is not.

Python 3.9 added numerous new names to modules, including:

- ast.unparse
- four new functions to the curses module
- two new constants to fcntl
- math.nextafter and .ulp

etc.

Secondly, in practice people do their wildcard imports at the start 
of the module, so they can make use of those names in their script or 
application:

    from tkinter import *
    window = Tk()

If the module adds a new name that you aren't expecting and aren't 
using, it just sits there harmlessly in your application's namespace. It 
doesn't prevent you using that name for your own purposes, so it can't 
break your code unless you do the star import after other imports or 
definitions.

Sure, you can do that star import in the middle of your code. But 
consenting adults applies. If you do that, you're supposed to know what 
you are doing.

So we seem to be worrying about a non-problem here. Adding a new 
Infinity name to builtins, or some other module, won't break backwards 
compatibility.

But what will break backwards compatibility is either:

- making Infinity a keyword, like None;

- or changing the repr of math.inf to 'Infinity'.


[Stephen]
> Also someone needs to explain how to avoid the debacle that was the
> the name collisions with True and False when the bool type was
> introduced.

What debacle are you referring to? Are you referring to the addition of 
the bools in the 2.2.1 bugfix release?

If so, we avoid that these days by just not adding new features to 
bugfix releases.

I don't know what name collisions you are referring to. In 2.2.1, new 
builtins bool (a function), True (the int 1) and False (the int 0) where 
added to allow people to backport code written for 2.3 which contained 
the proper bool type and special True/False singletons.

Adding these didn't cause name collisions. If your module already 
included globals 

    False = 0
    True = not False

they would quitely and harmlessly shadow the builtins and all was well.
     
The whole transition was remarkable smooth:

- PEP 285 introduced a new builtin bool type, with two named singletons 
  True and False;

  https://www.python.org/dev/peps/pep-0285/

- a bool *function*, with two named values True=1 and False=0, were 
  retroactively added to 2.2.1 (adding these to a bugfix release was an 
  annoyance, but hardly a debacle);

- and the True and False names didn't become keywords until Python 3.

See here for more background on it:

https://python-history.blogspot.com/2013/11/story-of-none-true-false.html

https://python-history.blogspot.com/2013/11/the-history-of-bool-true-and-false.html


-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/2G63DIJQ3VNAKQSS3NXRRQZ6G744GX33/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to