Reputation: 1379
PyCharm isn't importing/resolving properly. The code runs okay, but it isn't getting code completion, and is flagging up as errors (red squiggly lines).
The code that demonstrates this is as follows:
from turtle import *
forward(40)
right(45)
forward(80)
import turtle
t = turtle.Turtle()
t.forward(40)
t.right(45)
t.forward(80)
And a picture that demonstrates the issue in PyCharm:
Does anyone have any ideas on how to solve this problem? It's pretty annoying to not be able to use from X import Y
.
Upvotes: 0
Views: 1709
Reputation: 41872
What's going on here is that Python turtle is unusual in that it has two different interfaces, a functional one and an object-oriented one. If you use the object-oriented one, everything should work fine:
from turtle import Screen, Turtle
yertle = Turtle()
yertle.forward(40)
yertle.right(45)
yertle.forward(80)
screen = Screen()
screen.exitonclick()
The functional interface is there to make things easier for beginners:
from turtle import *
forward(40)
right(45)
forward(80)
exitonclick()
or:
import turtle
turtle.forward(40)
turtle.right(45)
turtle.forward(80)
turtle.exitonclick()
But you shouldn't mix the two! As that is a primary source of turtle confusion.
The issue with PyCharm is that the turtle functional API is derived from the object-oriented API at load time, so it's not there for PyCharm to find when it scans the source file. The turtle methods are all mapped onto the default turtle and screen methods are all mapped onto the singular screen instance.
Upvotes: 0
Reputation: 81614
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.
Upvotes: 2