简体   繁体   English

为什么我需要在这些 Python Tkinter 函数中使用星号和一些随机变量才能正常工作?

[英]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:我的问题是:

  1. Why do I need a parameter in those functions at all?为什么我在这些函数中需要一个参数?
  2. How does the variable "*randomVariable" get used, since it seems like I'm not actually using/ assigning anything to "randomVariable" anywhere within the function.如何使用变量“*randomVariable”,因为看起来我实际上并没有在 function 的任何地方使用/分配任何东西给“randomVariable”。
  3. Why does the function not work as intended without the asterisk before the variable?为什么变量前没有星号,function 不能按预期工作?

Thanks for your question and for providing a runnable code snippet!感谢您提出问题并提供可运行的代码片段!

Conclusion (TL;DR)结论(TL;DR)

  • You're using the same function to handle two different kinds of events (button push, keystroke).您正在使用相同的 function 来处理两种不同类型的事件(按钮按下、击键)。
  • Because of this, your function has to handle different numbers of arguments因此,您的 function 必须处理不同数量的 arguments
  • Using * gives your function this kind of flexibility使用*给你的 function 这种灵活性

About the * (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 ?"所以现在的问题是“ *argsargs有什么区别?” 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)实际上做了两件事:
    1. Unpack the list解压清单
    2. Print the elements of the list one-by-one一张一张打印列表的元素

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) <-- 没有方括号

Finding out why you need the * 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()用于两个不同的事情:

  • For a Button command: ttk.Button(..., command=changeTextEnter)对于 Button 命令: ttk.Button(..., command=changeTextEnter)
  • For a key binding: 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

Side notes旁注

  • If you aren't interested in the <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.这只会“吞下”任何位置 arguments。 The _ name is a convention for "I don't care about this" _名称是“我不在乎这个”的约定
  • One of the most prominent functions using * 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.

相关问题 如何在 tkinter python 中的两个函数之间传递变量? - How do I pass a variable between two functions in tkinter python? 为什么不起作用? (tkinter,python和函数) - Why won't this work? (tkinter, python and functions) 如何正确使用带有 tkinter 的表? - How do I properly work with Tables with tkinter? 我正在尝试让文本小部件功能在 python tkinter 中正常工作 - I'm trying to get the Text widget functions to work properly in python tkinter 为什么有些库只编写私有类函数然后分配一个公开它们的公共变量? - Why do some libraries write private class functions only to then assign a public variable exposing them? python:为什么我需要将生成器 function 分配给变量,否则它将不起作用? - python: why do I need to assign a generator function to a variable or it won't work? 两个函数在使用 sqlite3 的 tkinter python 中无法正常工作 - Two functions don't work properly in tkinter python with sqlite3 为什么在将lambda函数赋值给变量时需要括号? - Why do I need brackets around lambda functions when assigning them to variables? 为什么Python中的一些函数把\改为\\ - Why do some functions in Python change \ to \\ 为什么 python 的 random 模块中的某些方法在没有类实例的情况下工作? - Why do some of the methods in python's random module work without a class instance?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM