我的理解是,一个tkinter程序的标准设置通常是这样开始的:
from tkinter import *
from tkinter import ttk
我知道tkinter是一个包,但如果我已经使用*
导入了所有东西,为什么我还需要导入ttk
?如果我删除第二行并尝试引用ttk
,为什么会出现错误?
我的理解是,一个tkinter程序的标准设置通常是这样开始的:
from tkinter import *
from tkinter import ttk
我知道tkinter是一个包,但如果我已经使用*
导入了所有东西,为什么我还需要导入ttk
?如果我删除第二行并尝试引用ttk
,为什么会出现错误?
from some_package import *
时,Python会导入该包选择要导出的任何内容。它选择导出的内容可能是存储在包文件夹中的子集。为什么?没有特别的原因,这只是包作者决定做事情的方式。__init__.py
文件中定义(在本例中是tkinter/init.py)。如果你查看那个文件,你会注意到它并没有导入ttk本身,因此ttk不会被导出,因此不能使用通配符导入导入。# python 3.x
import tkinter as tk
from tkinter import ttk
# python 2.x
import Tkinter as tk
import ttk
这将使你的代码更易于阅读,因为你必须明确指出你正在使用哪个工具包:
b1 = tk.Button(...) # uses a standard tk button
b2 = ttk.Button(...) # uses a ttk button
我想不出任何其他好的理由来以其他方式进行操作。全局导入虽然可以在每次调用tkinter函数时节省几个字节,但会牺牲代码的清晰度。此外,它还会强化一种可能渗透到您使用其他库的不良实践。
在我看来,真正的权威是PEP8,它对此问题有以下建议:
应避免使用通配符导入(from import *),因为这会使命名空间中存在哪些名称变得不清楚,这使读者和许多自动化工具感到困惑。有一种可辩解的情况需要使用通配符导入,即将内部接口重新发布为公共API的一部分(例如,将一个接口的纯Python实现覆盖为一个可选加速器模块的定义,并且无法预先知道将覆盖哪些定义)。
tk
别名更加整洁),但这并没有回答 OP 的问题。 - jonrsharpe因为tkinter/__init__.py
没有导入ttk
,所以from tkinter import *
不会包含ttk
。
from tkinter import *
导入文件/包tkinter
,但这并不意味着它会从文件/包tkinter.ttk
中导入。这里其他两个答案没有提到的是,ttk没有被导入,因为它是tkinter模块中的一个子模块,实际上是一个独立的模块。
所以当你导入tkinter时,你会得到所有直接属于tkinter的部分。
但是ttk不直接属于tkinter,因此必须显式地导入。
然而,Bryan Oakley指出了一个很好的观点,即将一个模块中的所有内容导入本地命名空间(许多新手都这样做)可能会在以后使用更多模块时导致大问题。这是因为这些模块中的一些可能共享函数名称,即使这些函数本身可能完全不同。
对于大型模块来说,最好总是这样做:
import module as mod
或者
import module
然后将函数作为模块命名空间的一部分进行引用:
module.function()
这样做可以让你更好地控制自己的操作,并且在后面更清晰地知道该函数实际上属于哪个部分。