为什么Python的导入不能像C的#include一样工作?

我一直在试图理解Python导入大约一年了,而且我已经放弃了Python中的编程,因为它看起来似乎太混淆了。 我来自C背景,我认为import就像#include一样,但如果我尝试导入某些东西,我总会得到错误。

如果我有两个这样的文件:

foo.py:

 a = 1 

bar.py:

 import foo print foo.a input() 

为什么需要引用模块名称? 为什么不能只编写import fooprint a ? 这种混乱有什么意义? 为什么不运行代码并为您定义的东西,就像您在一个大文件中编写它一样? 为什么它不能像C的#include指令一样工作,它基本上复制和粘贴你的代码? 我在C中没有导入问题

要做你想做的事,你可以使用(不推荐,进一步阅读解释):

 from foo import * 

这会将所有内容导入到您当前的命名空间,您将能够调用print a

但是,这种方法的问题如下。 考虑具有两个模块moduleAmoduleB ,每个模块都有一个名为GetSomeValue()的函数。 当你这样做时:

 from moduleA import * from moduleB import * 

你有一个命名空间解析问题*,因为你用GetSomeValue()moduleA.GetSomeValue()moduleB.GetSomeValue()实际调用了什么函数?

除此之外,您还可以使用“ Import Asfunction:

 from moduleA import GetSomeValue as AGetSomeValue from moduleB import GetSomeValue as BGetSomeValue 

要么

 import moduleA.GetSomeValue as AGetSomeValue import moduleB.GetSomeValue as BGetSomeValue 

此方法可手动解决冲突。

我相信您可以从这些示例中了解显式引用的必要性。

* Python有其命名空间解析机制,这只是为了解释的目的而进行的简化。

想象一下,你的模块中有一个函数可以从列表中选择一些对象:

 def choice(somelist): ... 

现在想象一下,无论是在该函数中还是在模块的其他位置,您都在使用random库中的randint

 a = randint(1, x) 

所以我们

 import random 

你的建议是,这可以通过from random import *访问,这意味着我们现在有两个不同的函数叫做choice ,因为random包含了一个。 只有一个是可访问的,但是你引入了一个含糊不清的choice()实际引用代码中的其他地方。

这就是为什么导入一切都是不好的做法; 要么输入你需要的东西:

 from random import randint ... a = randint(1, x) 

或整个模块:

 import random ... a = random.randint(1, x) 

这有两个好处:

  1. 您可以最大限度地降低名称重叠的风险(现在和将来添加到导入的模块中); 和
  2. 当其他人读取您的代码时,他们可以轻松查看外部函数的来源。

有几个很好的理由。 该模块为其中的对象提供了一种命名空间,允许您使用简单的名称而不用担心冲突 – 来自C背景,您肯定会看到具有长而丑陋的函数名称的库,以避免与任何其他人发生冲突。

此外,模块本身也是对象 。 当在python程序中的多个位置导入模块时,每个模块实际上都获得相同的引用。 这样,改变foo.a改变每个人,而不仅仅是本地模块。 这与C形成鲜明对比,其中包含头部基本上是对源文件的复制+粘贴操作(显然你仍然可以共享变量,但机制有点不同)。

如上所述,您可以from foo import *from foo import a更好地说,但要了解底层行为实际上是不同的,因为您正在将a绑定到本地模块。

如果您经常使用某些内容,则可以始终使用from语法直接导入它,或者您可以将模块重命名为更短的内容,例如

 import itertools as it 

import foo ,会在名为foo的当前名称空间内创建一个新module

所以,要在foo中使用任何东西; 你必须通过模块解决它。

但是,如果您使用from from foo import something ,则无需使用前置模块名称,因为它将从模块加载something并为其分配名称。 (不推荐做法)