为什么要导入*然后ttk?

tem*_*ame 10 tk-toolkit tkinter python-3.x

我的理解是tkinter程序的标准设置就像这样开始:

from tkinter import *
from tkinter import ttk
Run Code Online (Sandbox Code Playgroud)

我知道tkinter是一个包,但如果我已经导入了所有包,我*为什么还需要导入ttk呢?如果我拿出第二行并尝试引用,为什么会出现错误ttk

Bry*_*ley 17

当你这样做时from some_package import *,python将导入包选择导出的任何内容.它选择导出的内容可能是实际存储在包文件夹中的一部分.这是为什么?没有特别的原因,这就是包裹作者决定如何做事.

有关导出内容的信息__init__.py在包内的文件中定义(在本例中为tkinter/init .py).如果查看该文件,您会注意到它不会导入ttk本身,因此不会导出ttk,因此无法使用通配符导入导入.

再说一遍,除了tkinter和ttk的作者选择做事之外,没有特别的理由.

有关打包机制的更多信息,请参阅python教程的包装部分(https://docs.python.org/3/tutorial/modules.html#packages)

导入tkinter的更好方法

您可能认为它是标准的,因为许多教程都是这样做的,但这通常是一种不好的做法.IMO的更好方法是给tkinter库一个明确的名称:

# python 3.x
import tkinter as tk
from tkinter import ttk 

# python 2.x
import Tkinter as tk
import ttk
Run Code Online (Sandbox Code Playgroud)

这将使您的代码更容易阅读,因为您必须明确说明您正在使用哪个工具包:

b1 = tk.Button(...) # uses a standard tk button
b2 = ttk.Button(...) # uses a ttk button
Run Code Online (Sandbox Code Playgroud)

我认为没有任何其他方式可以做到这一点.每次调用tkinter函数时,执行全局导入会为您节省几个字节,但代价是清晰度.此外,它强化了一种可能会影响您使用其他库的不良做法.

真正的权威,IMO,是PEP8,在此事上有这样的说法:

应避免使用通配符导入(来自import*),因为它们不清楚命名空间中存在哪些名称,这会使读者和许多自动化工具混淆.通配符导入有一个可防御的用例,即将内部接口重新发布为公共API的一部分(例如,使用可选加速器模块中的定义覆盖接口的纯Python实现,以及确切的定义将是被覆盖的事先不知道).


jon*_*rpe 5

因为tkinter/__init__.py没有import ttk,所以ttk不包含在中from tkinter import *