我正在Tkinter中创建简单的记事本程序。我决定将函数放在单独的文件中。如果函数对主文件中声明的变量进行操作,是否可能?这是代码片段:main.py
from tkinter import *
from otherfile import cut
root = Tk()
....
menu_edit.add_command(label='Cut', compound='left', command=cut)
...
main_text = Text(root, wrap ='word')
main_text.pack(expand='yes', fill = 'both')
现在我有otherfile.py
def cut():
main_text.event_generate('<<Cut>>')
return 'break'
一旦我运行它,我将得到:Tkinter回调中的异常
Traceback (most recent call last):
File "C:...\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "C:\....otherfile.py", line 3, in cut
main_text.event_generate('<<Cut>>')
NameError: name 'main_text' is not defined
所以我猜otherfile.py不理解main.py中定义的main_text。有没有办法绕过它,并允许我将所有功能放在不同的py文件中?
cut
正在尝试使用另一个文件中的全局变量。即使你找到了解决循环进口的方法,但这也是一种混乱的方式。编写独立于全局变量运行的函数会更好。首先,它使修改和测试更容易。当你需要处理分配command=function
和function
需要变量时,functools.partial是你的朋友。
def cut(tk_text_obj):
tk_text_obj.event_generate('<<Cut>>')
return 'break'
然后在主文件中,首先声明main_text
,然后使用functools.partial
创建一个不带参数的可调用对象。
from functools import partial
from tkinter import *
from otherfile import cut
root = Tk()
....
main_text = Text(root, wrap ='word')
cut_main_text = partial(cut, main_text)
menu_edit.add_command(label='Cut', compound='left', command=cut_main_text)
# or just combine the above two lines using command=partial(cut, main_text)
...
main_text.pack(expand='yes', fill = 'both')
有可能的。您应该在main
中导入otherfile
或修改otherfile.cut
方法以接受main_text作为方法参数。如果menu_edit.add_command
允许将参数传递给命令,则第二个选项取决于该选项。
我认为你有两个问题。
我相信下面的例子是你的情况。
啊.朋友:
import b
commands = []
def add_command(cmd):
commands.append(cmd)
def run_commands():
for cmd in commands:
print cmd()
def local_cmd():
return 'local cmd output'
if __name__ == '__main__':
add_command(local_cmd)
add_command(b.b_cmd)
run_commands()
不.朋友:
import a
def b_cmd():
l = a.local_cmd()
return 'B %s B' % l
当使用python a.py
运行时,上面的代码片段按预期工作。
但是当你跳过if __name__ == '__main__':
时,你会发现类似的情况。脚本失败是因为当您在a
中导入b
时,add_command(b.b_cmd)
中的a
被调用,但b
尚未导入。
使用全局变量是一种不好的做法和头痛。我可以建议修改cut()
来获取参数:
# otherfile.py
def cut(text_control):
text_control.event_generate('<<Cut>>')
return 'break'
然后在主模块中,将其调用为:
# main.py
menu_edit.add_command(label='Cut', compound='left', command=lambda: cut(main_text))
这样,您不必在以后处理麻烦。此外,如果需要,您现在可以将函数cut()
用于其他文本框。