This is an issue concerning scope. If you set a command using a string, then it is going to expect these symbols to be available in the global scope. But you are declaring inner functions that disappear after the dual() scope ends. There is no closure happening here.
My initial question is, do you need to use an inner function as your callback? Also, do you need to be using the string form of defining a command?
Ideally you would always pass a callable object as your command so that you don't have to deal with scope problems when the string is evaluated later on.
If you must use inner functions for your solution, then you should create a proper closure, and then pass a callable:
def dual():
def saves():
print "hello"
def load():
print "bye"
def callback(*args):
saves()
load()
with pm.window(width=150):
pm.columnLayout(adj=True)
pm.button(label="Button 1", command=callback)
Justin