[Tutor] why can use a widget assigned to a variable or just use it on it's own?

Alan Gauld alan.gauld at yahoo.co.uk
Mon Jul 2 03:40:19 EDT 2018

On 02/07/18 02:54, Chris Roy-Smith wrote:

> If I have grasped things correctly a widget is an object. 

Every value in Python is an object.

numbers, strings, lists, functions, instances of classes.
All are objects.
You can see that by using the dir() function on them:

>>> dir(5)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__',
'__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__',
'__float__', '__floor__', '__floordiv__', '__format__', '__ge__',
'__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__',
'__init__', '__init_subclass__', '__int__', '__invert__', '__le__',
'__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__',
'__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__',
'__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__',
'__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__',
'__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
'__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__',
'__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__',
'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag',
'numerator', 'real', 'to_bytes']
>>> dir(print)
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__name__', '__ne__', '__new__', '__qualname__', '__reduce__',
'__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__text_signature__']

Those are all the attributes and methods/operations that
you can access for a number and a function.

And so, yes, widgets are also objects...They are instances
of classes.

> from tkinter import *
> main=Tk()

main is now a reference to an instance of the top level
Tkinter class, Tk.

> # as I understand it this will create an instance of the button widget 
> called b1
> b1=Button(main, text='instantce', command= lambda b='goodbye' : 
> print(b)).grid(row=1, column=0)

No, this will create an instance of the Button class but it
will not be called b1. You call grid() on your instance and
grid always returns None. So b1 stores a reference to None.
(Note that None is also an object!)

> # but here I haven't made an instance, but all seems well
> Button(main, text='test1', command=lambda a='hello' 
> :print(a)).grid(row=0, column=0)

You have made an instance, exactly like before.
The instance is created by you calling the class:

Button(.....)   # creates an instance

b = Button(.....) ' creates instance and stores a reference in b

b = Button(...).grid() # creates instance and
                       # calls its grid method returning None to b

Everything works because when you create a widget
instance the first argument is always the parent widget.
Inside the widget __init__() method the code looks something
like this:

def __init__(...):

So one of the first things the widget does is add itself
to its parent's list of child widgets. That means that there
is a reference to the widget inside parent whether you
store a local reference or not. As a result the widget
is not immediately destroyed.

> any explanation gratefully received

Hopefully that helps.

Alan G
Author of the Learn to Program web site
Follow my photo-blog on Flickr at:

More information about the Tutor mailing list