As a rule of thumb, do not use from X import *
, regardless of what package X is or what its documentation says, It will only lead to bugs later down the road.
Why "star imports" should be avoided
from turtle import *
def forward():
print('forward')
forward(45)
What do you think will happen?
turtle.forward
is overwritten by the locally defined forward
function, and we will get an error TypeError: forward() takes 0 positional arguments but 1 was given
Why it works in this case
from turtle import *
forward(40)
To understand why the above works even though Pycharm says that forward
is not defined we have to see how the turtle
module is implemented, and then understand how Python imports work and how Pycharm checks for "definitions" of used names.
turtle.py
tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
_tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
'register_shape', 'resetscreen', 'screensize', 'setup',
'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
'window_height', 'window_width']
_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
'fillcolor', 'filling', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
'write', 'xcor', 'ycor']
_tg_utilities = ['write_docstringdict', 'done']
__all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
_tg_utilities + ['Terminator'])
...
As you can see, it simply prepares some lists of strings (which are names of functions/classes/etc) then concats everything to a single list and assigns everything to the __all__
global variable.
I will not go into much details about __all__
(since there are several Q&A on SO on that topic, for example Can someone explain __all__ in Python?), but basically it tells the interpreter what names should be available when doing from X import *
.
When you are doing from turtle import *
then using forward
, right
etc, they are available to use since their name is inside __all__
, but Pycharm has no idea that they will be exposed by __all__
at runtime.