0

This is a section from my code. Basically, I want access to the value given in the entry box, which is a part of the def init ..Is there any way around this without using global variables? Also, it is set up this way so that this variable can be used throughout my program. Thanks.

import tkinter as tk

class MainApp(tk.Tk):

def test():
    a = __init__.test_entry.get()
    print(a)

def __init__(self, *args, **kwargs):
    tk.Tk.__init__(self, *args, **kwargs)

    test_entry = tk.Entry(self)
    test_entry.pack()

    submit_button = tk.Button(self, text="Submit", command=MyApp.test)
    submit_button.pack()

if __name__ == "__main__":
    app = MainApp()
    app.mainloop()
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
monto
  • 49
  • 7

2 Answers2

2

No, there's no way for an external function to access the local variables defined in a function.

There are several ways to solve the problem you have without that though. You could make the variables defined in __init__ instance variables (attributes of self) and make sure your external function can access the right instance (perhaps in a global variable).

Or you could define a function within the __init__ function. Such a closure can access the variables defined in an outer namespace without issue. In your specific instance, you could even make the closure a really small one, using lambda to call the "real" outer function with an argument:

class MainApp(tk.Tk):
    def test(test_entry):
        a = test_entry.get()
        print(a)

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        test_entry = tk.Entry(self)
        test_entry.pack()

        submit_button = tk.Button(self, text="Submit", command=lambda: MyApp.test(test_entry))
        submit_button.pack()

The expression lambda: MyApp.test(test_entry) defines an unnamed function that keeps hold of the test_entry defined in the namespace of the __init__ method. When the lambda function is called, it passes that value on to the test function. You could also move the whole test definition into the __init__ method, and so call it directly, without a lambda, but that is often ugly as it involves lots of deep indentation.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
0

I'm not sure if i understand you correctly tbh

Have you considered using this instead?
self.__test_entry = tk.Entry(self)

David Peters
  • 90
  • 1
  • 6
  • This way the variable is private (not 100% correct, see [here](https://stackoverflow.com/questions/1641219/does-python-have-private-variables-in-classes#1641236)) – David Peters Feb 21 '19 at 22:19
  • No, it isn't. Python *doesn't have private variables*. By *convention*, you should use a *single-underscore* for variables that are not part of the public API – juanpa.arrivillaga Feb 21 '19 at 22:20
  • I get an error __init__.test_entry.get() is not defined. After making changes you suggested I still get that error. I am trying to get access to the test_entry within _init_, but am failing horribly lol. – monto Feb 21 '19 at 22:21
  • @monto Firstly, `__init__` is not defined in that scope. Second, even if it were and were referring to `MainApp.__init__`, the *local variables* are not accessible as attributes to the function. That would sort of defeat the purpose of local variables – juanpa.arrivillaga Feb 21 '19 at 22:23
  • @monto you would also need to change the line in test to a = self.__test_entry.get() also consider using only one underscore as juanpa.arrivillaga proposed – David Peters Feb 21 '19 at 22:30
  • After doing this I get the error, "NameError: name 'self' is not defined" – monto Feb 21 '19 at 22:35
  • You also need to change to "def test(self):" and to "self.__test_entry.pack()" for this to work, please look at the python documentation and some tutorials about variable scope and objects in python – David Peters Feb 21 '19 at 22:40