[Tutor] Class Inheritance
Steven D'Aprano
steve at pearwood.info
Fri Apr 23 07:51:22 CEST 2010
On Fri, 23 Apr 2010 03:11:36 pm David Hutto wrote:
> Hello List!
>
> While experimenting with Tkinter(python2.6), when from Tkinter
> import* is used I came across the following error:
> ************
> C:\Users\ascent>c:\python26/Script3.py
> Traceback (most recent call last):
> File "C:\python26\Script3.py", line 1, in <module>
> from Tkinter import *
> File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in <module>
> from turtle import *
> File "C:\Python26\lib\lib-tk\turtle.py", line 374, in <module>
> class ScrolledCanvas(Tkinter.Frame):
> AttributeError: 'module' object has no attribute 'Frame'
Something is screwy there. I believe you have broken your installation
by making changes to files without having any understanding of what you
are doing.
The turtle module does this:
import Tkinter as TK
so that line should be "class ScrolledCanvas(TK.Frame)", and in fact
that's what I find when I go and look at the source code:
class ScrolledCanvas(TK.Frame):
The line number is different too. How many breakages have you introduced
to the library?
> Which stems from the below in turtle.py:
>
> class ScrolledCanvas(TK.Frame)
Note the difference between Tkinter.Frame and TK.Frame.
> I know that ScrolledCanvas is trying to use class TK.Frame as it's
> base class to build from, and the class Frame is what is trying to be
> called from the Tkinter module.
>
> So I tried to alter the turtle.py.
Please don't try to "fix" library files when you don't understand what
they are doing. Confine your experiments to your own code, so that when
things break, you know that the cause is in your code, not some random
change you have done to the library.
> When I try to just 'from Tkinter
> import *, such as:
>
> from Tkinter import *
> class ScrolledCanvas(Tkinter.Frame):
That won't work, because there is no Tkinter defined.
One wrong way to do it is:
from Tkinter import *
class ScrolledCanvas(Frame):
but that risks stomping over the top of other variables with great big
hob-nailed boots. Better to avoid import *, and do this:
import Tkinter
class ScrolledCanvas(Tkinter.Frame):
but that's still a silly thing to do, because the turtle module has
already imported Tkinter. The right way is to leave the module alone,
it was working before you changed it:
import Tkinter as TK
class ScrolledCanvas(TK.Frame):
> I get:
> *****************
> C:\Users\ascent>c:\python26/Script3.py
> Traceback (most recent call last):
> File "C:\python26\Script3.py", line 1, in <module>
> from Tkinter import *
> File "C:\Python26\lib\lib-tk\Tkinter.py", line 44, in <module>
> from turtle import *
> File "C:\Python26\lib\lib-tk\turtle.py", line 373, in <module>
> class ScrolledCanvas(Tkinter.Frame):
> NameError: name 'Tkinter' is not defined
Now you have two errors.
(1) You have introduced a circular import dependency, where turtle tries
to import Tkinter which tries to import Tkinter which tries to import
turtle...
(2) You have no Tkinter object, since you import it's contents, not the
module itself.
> I know pretty much what is going on there.
I doubt it, or else you wouldn't have done what you did.
> But when I try to use:
>
> import Tkinter
> from Tkinter import *
Why would you do that when turtle has already imported Tkinter under the
name TK?
> class ScrolledCanvas(Tkinter.Frame):
>
> It takes me back to the first error. Which means
> in both instances both directly called by me, and
> when called from the original turtle.py call,
> it's not finding the Frame class.
I suspect you've broken it. I recommend you re-install the Tkinter
library, including turtle.py, in order to get it back to a known
working state.
> >From the docs (9.5. Inheritance) it states:
>
> "The name BaseClassName must be defined in a
> scope containing the derived class definition.
> In place of a base class name, other arbitrary
> expressions are also allowed. This can be useful,
> for example, when the base class is defined in another module:
>
> class DerivedClassName(modname.BaseClassName)
> "
>
>
> So why does the above, from turtle.py, a standard module,
> not allow this, or is their something
> the module writer got wrong, or more likely, that I'm not
> understanding about what it's doing?
I don't have this problem with an unmodified version of turtle and
Tkinter in Python 2.6. I get:
>>> import turtle
>>> turtle.TK.Frame
<class Tkinter.Frame at 0x00BC2F60>
>>> turtle.ScrolledCanvas
<class turtle.ScrolledCanvas at 0x00F71720>
> As a sidenote, I ended up removing the from turtle import *
> line from Tkinter which resolved the problem(the example I was using
> didn't have a canvas, and I'm pretty sure Tkinter was defaulting
> to the ScrolledCanvas).
I should say so! Tkinter doesn't have a "from turtle import *" line, as
that would set up a circular import dependency. No wonder you have had
problems, making random changes to libraries without understanding
them.
--
Steven D'Aprano
More information about the Tutor
mailing list