import tkinter as tk
win = tk.Tk()
text = tk.Text(win, width = 50, height = 20, bg = 'black', fg = 'lightgreen', wrap = tk.WORD)
text.pack()
text.tag_configure('prompt', foreground = 'magenta')
text.tag_configure('output', foreground = 'yellow')
text.insert('end', '>>> ', 'prompt')
def on_return(*args):
cmd = text.get('prompt.last', 'end')
if cmd:
try:
output = str(eval(cmd, globals = {"__builtins__":None}))
except Exception as e:
output = str(e)
text.insert('end', '\n' + output, 'output')
text.insert('end', '\n>>> ' + output, 'prompt')
return 'break'
text.bind('<Return>', on_return)
win.mainloop()
为了获得此输出:eval() 不接受关键字参数,只需在文本小部件上键入任何内容,然后按 Enter 键。
我应该怎么做才能避免这种输出?
在代码中,您需要从字典中传递的参数中删除“globals =”。正确的行是:
output = str(eval(cmd, {"__builtins__":None}))
默认情况下,当您声明函数时,可以通过名称或关键字传递参数。但是,可以声明一个函数以禁止位置或关键字传递。许多内置函数(例如
eval
和 range
)都使用它来减少调用时间,允许库所有者自由重命名参数,并禁止奇怪的调用顺序。 请参阅 PEP 570 了解更多信息。
要调用这些函数,您必须以正确的顺序给出参数。如果您只想提供
eval
局部变量,而不是全局变量,只需传递 global
的默认值: eval(expression, None, your_locals)
.
您可以通过在参数列表中添加正斜杠
/
和星号 *
来声明这样的函数。斜杠之前的参数仅是位置参数,斜杠和星号之间的参数是关键字或位置参数,星号之后的参数仅是关键字。
例如,要获得类似于 eval 的行为,您可以声明:
def eval2(expression, globals=None, locals=None, /):
pass
eval2
仅接受位置参数。如果你用关键字调用它,你会得到一个异常:
eval2('print("hello", location)', locals={'location':'world'})
...
TypeError: eval2() got some positional-only arguments passed as keyword arguments: 'locals'
您还可以声明一个混合使用仅位置参数、普通参数和仅关键字参数的函数:
def example_function(positional1, positional2, /, keyword_or_positional1, keyword_or_positional2, *, keyword1, keyword2):
pass
顺便说一句,这也是您在 Python 帮助实用程序中的某些签名中看到斜杠的原因:
help(hasattr)
...
hasattr(obj, name, /)
因为 obj 和 name 位于斜杠之前,所以它们不能作为关键字参数传递。由于某种原因,除非有普通参数以及仅位置参数,否则 HTML 文档中不包含斜杠。