Hiya :)

I'm recently working with tkinter and I noticed that:

>>> import tkinter as tk
>>> string_var = tk.StringVar()

is throwing an AttributeError:

> Traceback (most recent call last):
>   . . .
>   File "...\lib\tkinter\__init__.py", line 505, in __init__
>     Variable.__init__(self, master, value, name)
>   File "...\lib\tkinter\__init__.py", line 335, in __init__
>     self._root = master._root()
> AttributeError: 'NoneType' object has no attribute '_root'

... which is making me question myself:
-- "Why am I looking for a '_root' attribute on a NoneType object here?", or
-- "How did I end up with a NoneType, to be searched for a '_root' attribute in the first place?"
I have done something wrong or I don't know something apparently.

Following the traceback, looking at "tkinter\__init__.py", lines 333-335 leads us to the implementation of StringVar's parent: class Variable:

333 >         if not master:
334 >             master = _default_root
335 >         self._root = master._root()

Class Variable constructor interface:

317 >     def __init__(self, master=None, value=None, name=None):

Clearly, on line 335, we are relying on the "master" to have a "_root" callable. If "master" was not declared upon class instantiation (line 317), a value can come from _default_root, which is a global module variable. _default_root is holding a Tk instance, if one was instantiated. So, if neither "master" nor _default_root was defined, line 335 will result in an AttributeError.

Now, would it be a good idea if we keep the user better informed by making the aforementioned lines look something like?:

333 >         if not master:
334 >             master = _default_root
335 >             if not master:
336 >                 raise RuntimeError(f"{self.__class__.__name__!r}: 'master' must be defined or a Tk instance must be present!")
337 >         self._root = master._root()

... and not relying on this inexplicable AttributeError.

Thank you for your time!

Regards
Ivo Shipkaliev