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

时间:2014-03-14 14:47:46

标签: python c import

我实际上已经尝试了解大约一年的Python导入,而且我已经放弃了Python中的编程,因为它似乎太混淆了。我来自C背景,我认为import的工作方式与#include类似,但如果我尝试导入某些东西,我总会得到错误。

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

foo.py:

a = 1

bar.py:

import foo
print foo.a
input()

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

5 个答案:

答案 0 :(得分:9)

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

from foo import *

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

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

from moduleA import *
from moduleB import *

您有名称空间解析问题*,因为您实际使用GetSomeValue()moduleA.GetSomeValue()moduleB.GetSomeValue()调用了什么功能?

除此之外,您还可以使用Import As功能:

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

或者

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

此方法可手动解决冲突。

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

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

答案 1 :(得分:2)

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

def choice(somelist):
    ...

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

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. 当其他人阅读您的代码时,他们可以轻松查看外部功能的来源。

答案 2 :(得分:1)

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

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

如前所述,您可以说from foo import *或更好from foo import a,但要了解基础行为实际上是不同的,因为您正在使用a并将其绑定到本地模块。< / p>

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

import itertools as it

答案 3 :(得分:0)

执行import foo时,会在名为module的当前命名空间内创建新的foo

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

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

答案 4 :(得分:0)

Option Explicit

Private WithEvents moTextDate As MSForms.TextBox

Public Property Set DateTextBox(ByVal oTxtBox As MSForms.TextBox)
    Set moTextDate = oTxtBox
End Property

Private Sub moTextDate_Enter()
    ' Things to do on receiving focus
End Sub

Private Sub moTextDate_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    If ValidateNumbers(KeyAscii, "/", ":", " ") = False Then KeyAscii = 0
End Sub

Private Sub moTextDate_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    ' Things to do when lost focus
End Sub

例如:

import importlib

# works like C's #include, you always call it with include(<path>, __name__)
def include(file, module_name):
    spec = importlib.util.spec_from_file_location(module_name, file)
    mod = importlib.util.module_from_spec(spec)
    # spec.loader.exec_module(mod)
    o = spec.loader.get_code(module_name)
    exec(o, globals())

输出将是:

#### file a.py ####
a = 1

#### file b.py ####
b = 2

if __name__ == "__main__":
    print("Hi, this is b.py")

#### file main.py ####
# assuming you have `include` in scope 
include("a.py", __name__)
print(a)
include("b.py", __name__)
print(b)