为什么Python的导入不能像C的#include一样工作?
我一直在试图理解Python导入大约一年了,而且我已经放弃了Python中的编程,因为它看起来似乎太混淆了。 我来自C背景,我认为import
就像#include
一样,但如果我尝试导入某些东西,我总会得到错误。
如果我有两个这样的文件:
foo.py:
a = 1
bar.py:
import foo print foo.a input()
为什么需要引用模块名称? 为什么不能只编写import foo
, print a
? 这种混乱有什么意义? 为什么不运行代码并为您定义的东西,就像您在一个大文件中编写它一样? 为什么它不能像C的#include指令一样工作,它基本上复制和粘贴你的代码? 我在C中没有导入问题
要做你想做的事,你可以使用(不推荐,进一步阅读解释):
from foo import *
这会将所有内容导入到您当前的命名空间,您将能够调用print a
。
但是,这种方法的问题如下。 考虑具有两个模块moduleA
和moduleB
,每个模块都有一个名为GetSomeValue()
的函数。 当你这样做时:
from moduleA import * from moduleB import *
你有一个命名空间解析问题*,因为你用GetSomeValue()
, moduleA.GetSomeValue()
或moduleB.GetSomeValue()
实际调用了什么函数?
除此之外,您还可以使用“ Import As
function:
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)
这有两个好处:
- 您可以最大限度地降低名称重叠的风险(现在和将来添加到导入的模块中); 和
- 当其他人读取您的代码时,他们可以轻松查看外部函数的来源。
有几个很好的理由。 该模块为其中的对象提供了一种命名空间,允许您使用简单的名称而不用担心冲突 – 来自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
并为其分配名称。 (不推荐做法)