Let's have a look at your first piece of code:
from tkinter import *
def close_window(window_x):
window_x.destroy()
window_1= Tk()
button_1=Button(window_1,text="close",command=close_window(window_1))
button_1.pack()
window_1.mainloop()
So what's the issue?
The line
button_1=Button(window_1,text="close",command=close_window(window_1))
doesn't do what you're expecting it to. command=close_window(window_1) tells Python to run your function, and assign the result of it to the command argument. This means your function is executed, closing your window, and so you can't put your button in it, which is causing your error.
In your second snippet, it works because instead of assigning the result of the function call to the argument command, you're instead passing the function itself as an argument. When you click your button, your window will now close.
If you need to pass an argument to a function, consider adding a wrapper, or use a lambda statement, as such:
button_1=Button(window_1,text="close",command=lambda: close_window(window_1))
Edit:
If you want to use a wrapper, use this:
from tkinter import *
def args(*args, **kwargs):
def inner(func):
def wrapper():
return func(*args, **kwargs)
return wrapper
return inner
window_1= Tk()
@args(window_1)
def close_window(window_x):
window_x.destroy()
button_1=Button(window_1,text="close",command=close_window)
button_1.pack()
window_1.mainloop()
or if you need to have different arguments each time, use this:
from tkinter import *
def args(*args, **kwargs):
def inner(func):
def wrapper():
return func(*args, **kwargs)
return wrapper
return inner
def close_window(window_x):
window_x.destroy()
window_1= Tk()
button_1=Button(window_1,text="close",command=args(window_1)(close_window))
button_1.pack()
window_1.mainloop()