[Tutor] Help with class in class

Peter Otten __peter__ at web.de
Sun Sep 9 19:12:03 CEST 2012


leam hall wrote:

> I'm in the O'Reilly Python 2 class, so pointers to learning would be
> better than just answers, please. My brain is a bit slow but needs to go
> forward.
> 
> Line 16 calls line 31. Rather, it is supposed to. I'm trying to figure out
> why I get
> 
>   File "./ch8_project.py", line 31, in change_text_color
>     self.text.tag_configure('highlightline', foreground=fg_color)
> AttributeError: 'ch8_Project' object has no attribute 'text'
> 
> If line 31 starts with "self." and
> 
>   File "./ch8_project.py", line 31, in change_text_color
>     text.tag_configure('highlightline', foreground=fg_color)
> NameError: global name 'text' is not defined
> 
> 
> If Line 31 does not start with "self.". I understand the second problem
> but not the first.
> 
> What am I missing?

When inside a method you assign to

self.whatever = ...

you are setting an attribute of the class. If you assign to a name

whatever = ...

you are setting a local variable. So

> #!/usr/bin/env python3
> 
> from tkinter import *
> 
> SIDE = W+E 
> ALL = N+E+W+S
> 
> class ch8_Project(Frame):
> 
>   def __init__(self, master=None):
>     Frame.__init__(self, master)
>     self.file_open("./fred")
>     fg_color = "Red"
>     self.pack()
>     self.add_text_widget( fg_color, self.out_text)
>     self.green = Button(root, text="Green", 
command=self.change_text_color("green"))
>     self.green.pack(side=TOP)
> 
>   def add_text_widget(self, fg_color, out_text):
>     text = Text(root)

in the above line you are making a local variable which will be forgotten 
when the method terminates. Change the line to

      self.text = Text(root)

do the same for the following lines, and

>     text.insert(INSERT, out_text)
>     text.tag_configure('highlightline', foreground='red')
>     text.tag_add('highlightline', '1.0', 'end')
>     text.pack()
> 
>   def file_open(self, file_name):
>     file = open(file_name, "r")
>     self.out_text = file.read()
> 
>   def change_text_color(self, fg_color):
>     self.text.tag_configure('highlightline', foreground=fg_color)

the above will no longer complain about a missing attribute. 

> root = Tk()
> project = ch8_Project(master=root)
> project.mainloop()


Another problem that caught my attention:

>     self.green = Button(root, text="Green", 
command=self.change_text_color("green"))


The command argument is supposed to be a function; you are instead assigning 
the result of a method call (which is None in this case, but as a side 
effect will set the color to green immediately. The simplest fix is to 
define a helper function that takes no arguments
     ...
     def change_to_green():
         self.change_text_color("green")
     self.green = Button(root, text="Green", command=change_to_green)
     ...

If you already know about lambda you can try to rewrite this using that.



More information about the Tutor mailing list