我的理解是tkinter程序的标准设置就像这样开始:
from tkinter import *
from tkinter import ttk
我了解tkinter是一个软件包,但如果我已经使用*
导入了所有内容,为什么还需要导入ttk
?如果我拿出第二行并尝试引用ttk
?
答案 0 :(得分:16)
执行from some_package import *
时,python将导入包选择导出的内容。它选择导出的内容可能是实际存储在包文件夹中的一部分。这是为什么?没有特别的原因,它只是包裹作者决定如何做事。
有关导出内容的信息在包内的__init__.py
文件中定义(在本例中为tkinter/init.py)。如果您查看该文件,您会注意到它本身并不导入ttk,因此ttk不会被导出,因此无法通过通配符导入导入。
除此之外,没有特别的理由除了tkinter和ttk的作者如何选择做事。
有关包装机制的更多信息,请参阅python教程的包装部分(https://docs.python.org/3/tutorial/modules.html#packages)
您可能认为它是标准的,因为很多教程都是这样做的,但这通常是一种不好的做法。 IMO的更好方法是给tkinter库一个明确的名称:
# 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函数时,执行全局导入会为您节省几个字节,但代价是清晰度。此外,它强化了一种可能会影响您使用其他库的不良做法。
真正的权威,IMO,PEP8,在此问题上可以这样说:
应避免使用通配符导入(来自import *),因为它们不清楚命名空间中存在哪些名称,这会使读者和许多自动化工具混淆。通配符导入有一个可防御的用例,即将内部接口重新发布为公共API的一部分(例如,使用可选加速器模块中的定义覆盖接口的纯Python实现,以及确切的定义将是被覆盖的事先不知道。
答案 1 :(得分:3)
由于tkinter/__init__.py
没有import ttk
,因此ttk
中不包含from tkinter import *
。
答案 2 :(得分:0)
简要说明:from tkinter import *
从文件/数据包tkinter
导入,但这并不意味着它将从文件/数据包导入tkinter.ttk
答案 3 :(得分:-1)
这里的其他两个答案未能说明ttk未导入,因为它是tkinter模块中的子模块,实际上是一个模块。
因此,当您导入tkinter时,您将获得所有直接属于tkinter的部分
但是ttk不直接属于,因此必须明确导入。
然而,Bryan Oakley提出了一个很好的观点,即从模块导入到本地命名空间(正如许多新手那样)的所有东西都可能在以后开始使用更多模块时导致大问题。这是因为其中一些模块可能共享函数名称,即使函数本身可能完全不同。大型模块总是最好:
import module as mod
或
import module
然后将函数引用为属于modules命名空间:
module.function()
这使您可以更好地控制自己正在做的事情,并在以后更清楚地了解函数的实际属性。