为什么要导入*然后ttk?

时间:2014-07-13 18:31:44

标签: python-3.x tkinter tk

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

from tkinter import *
from tkinter import ttk

我了解tkinter是一个软件包,但如果我已经使用*导入了所有内容,为什么还需要导入ttk?如果我拿出第二行并尝试引用ttk

,为什么会出现错误

4 个答案:

答案 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

导入tkinter的更好方法

您可能认为它是标准的,因为很多教程都是这样做的,但这通常是一种不好的做法。 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()

这使您可以更好地控制自己正在做的事情,并在以后更清楚地了解函数的实际属性。