[英]Why do I need an asterisk and some random variable in these Python Tkinter functions for them to work properly?
In this basic Python Tkinter code, I'm trying to bind certain functions to trigger upon either a UI button press or a keyboard key press.在这个基本的 Python Tkinter 代码中,我试图绑定某些功能以在按下 UI 按钮或按下键盘按键时触发。
import tkinter as tk
from tkinter import ttk
main_window = tk.Tk()
main_window.title('Test UI')
# Change text with "Enter" then flush
def changeTextEnter():
text_label.configure(text=entry_bar.get())
entry_bar.delete(0, tk.END)
# Close program key function
def quitApp():
main_window.destroy()
# Enter Button
enter_button = ttk.Button(text='Enter', command=changeTextEnter)
enter_button.grid(row=0, column=0)
# Entry bar
entry_bar = ttk.Entry(width=30)
entry_bar.grid(row=0, column=1)
# Quit Button
quit_button = ttk.Button(text='Quit', command=main_window.destroy)
quit_button.grid(row=0, column=2)
# Text label
text_label = ttk.Label(text='TEST TEXT GOES HERE')
text_label.grid(row=1, column=0, columnspan=2)
# Bind enter key
main_window.bind('<Return>', changeTextEnter)
# Bind quit key
main_window.bind('<Escape>', quitApp)
main_window.mainloop()
After a while of trial and error, it seems to work the way I want if I add an经过一段时间的反复试验,如果我添加一个,它似乎可以按照我想要的方式工作
*randomVariable
in the declarations of:在以下声明中:
def changeTextEnter(*randomVariable):
and:和:
def quitApp(*randomVariable):
I get that one asterisk lets the function take an unknown number of arguments, and a double asterisk acts as a dictionary with key values.我知道一个星号让 function 采用未知数量的 arguments,而双星号充当带有键值的字典。
My questions are:我的问题是:
Thanks for your question and for providing a runnable code snippet!感谢您提出问题并提供可运行的代码片段!
*
gives your function this kind of flexibility*
给你的 function 这种灵活性*
(asterisk)*
(星号) You correctly mentioned that you can use *
in a function's parameter list to accept any number of positional arguments.您正确地提到您可以在函数的参数列表中使用
*
来接受任意数量的位置 arguments。 You probably have seen some function like this:你可能见过一些像这样的 function:
def my_func(*args, **kwargs):
...
So now the question is "what is the difference between *args
and args
?"所以现在的问题是“
*args
和args
有什么区别?” We can find the answer in the Python Language Reference :我们可以在Python 语言参考中找到答案:
An asterisk
*
denotes iterable unpacking.星号
*
表示可迭代解包。 Its operand must be an iterable.它的操作数必须是可迭代的。 The iterable is expanded into a sequence of items, which are included in the new tuple, list, or set, at the site of the unpacking.
可迭代对象被扩展为一系列项目,这些项目包含在解包地点的新元组、列表或集合中。
The important word here is unpacking .这里重要的词是unpacking 。 Consider this example:
考虑这个例子:
>>> my_list = [1, 2, 3]
>>> print(my_list)
[1, 2, 3]
>>> print(*my_list)
1 2 3
print(my_list)
just prints the list, nothing special here print(my_list)
只是打印列表,这里没什么特别的print(*my_list)
actually does two things: print(*my_list)
实际上做了两件事:
In other words:换句话说:
print(my_list)
is equivalent to print([1, 2, 3])
print(my_list)
等价于print([1, 2, 3])
print(*my_list)
is equivalent to print(1, 2, 3)
<-- no square brackets print(*my_list)
等价于print(1, 2, 3)
<-- 没有方括号*
in your code*
Here, I'll talk about the function changeTextEnter()
, but the same applies to quitApp()
.在这里,我将讨论 function
changeTextEnter()
,但同样适用于quitApp()
。
Basically, you're using changeTextEnter()
for two different things:基本上,您将
changeTextEnter()
用于两个不同的事情:
ttk.Button(..., command=changeTextEnter)
ttk.Button(..., command=changeTextEnter)
main_window.bind(..., changeTextEnter)
main_window.bind(..., changeTextEnter)
Pressing the "Enter" button and hitting the <Return>
key both call changeTextEnter()
, but in a different way (with different arguments).按下“Enter”按钮并按下
<Return>
键都调用changeTextEnter()
,但方式不同(使用不同的参数)。
You can use a debugger to observe this:您可以使用调试器来观察这一点:
def changeTextEnter(*args):
text_label.configure(text=entry_bar.get()) # <-- breakpoint here
entry_bar.delete(0, tk.END)
Another way is to print the value of args
:另一种方法是打印
args
的值:
def changeTextEnter(*args):
# DEBUG
print(args)
text_label.configure(text=entry_bar.get())
entry_bar.delete(0, tk.END)
Action![]() |
Value of args ![]() args 值 |
---|---|
Pushing the "Enter" button![]() |
() (empty tuple) ![]() () (空元组) |
Hitting the <Return> key ![]() <Return> 键 |
(<KeyPress event...>,) |
You original code can't handle the second case because the function doesn't expect a positional argument:您的原始代码无法处理第二种情况,因为 function 不需要位置参数:
TypeError: changeTextEnter() takes 0 positional arguments but 1 was given
<KeyPress event>
object, you can change your function definition to this: def changeTextEnter(*_)
.<KeyPress event>
object 不感兴趣,可以将 function 定义更改为: def changeTextEnter(*_)
。 This will just "swallow" any positional arguments._
name is a convention for "I don't care about this" _
名称是“我不在乎这个”的约定*
is the built-in print()
function.*
的最突出的函数之一是内置的print()
function。 Did you ever wonder how these calls work?:print()
print("Hello")
print("Cool number:", 42)
print("bla", "bla", end="")
Have a look at the function definition, it uses *
:看看 function 定义,它使用
*
:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.