从另一个文件调用函数,该文件包含在主文件中声明的变量

问题描述 投票:0回答:3

我正在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文件中?

python
3个回答
1
投票

cut正在尝试使用另一个文件中的全局变量。即使你找到了解决循环进口的方法,但这也是一种混乱的方式。编写独立于全局变量运行的函数会更好。首先,它使修改和测试更容易。当你需要处理分配command=functionfunction需要变量时,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')

0
投票

有可能的。您应该在main中导入otherfile或修改otherfile.cut方法以接受main_text作为方法参数。如果menu_edit.add_command允许将参数传递给命令,则第二个选项取决于该选项。

我认为你有两个问题。

  1. 循环进口这是一个真正的痛苦。
  2. 在模块导入期间调用在模块级别声明的所有内容。

我相信下面的例子是你的情况。

啊.朋友:

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尚未导入。


0
投票

使用全局变量是一种不好的做法和头痛。我可以建议修改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()用于其他文本框。

© www.soinside.com 2019 - 2024. All rights reserved.