[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