python import是什么_Python import 到底引入了什么

昨天学习小组里有人遇到了个奇怪的问题

AttributeError: 'module' object has no attribute 'model'

先看运行正常的代码

from PythonCard import model

class MainWindow(model.Background):

pass

app = model.Application(MainWindow)

app.MainLoop()

再看下面运行失败的

import PythonCard

class MainWindow(PythonCard.model.Background):

pass

app = PythonCard.model.Application(MainWindow)

app.MainLoop()

这两者似乎没有区别,那么错在了哪里呢?两种 import 到底有什么不同?我进行了初步实验。

from PythonCard import model

print model

print PythonCard

### 输出 ###

Traceback (most recent call last):

File "test.py", line 7, in

print PythonCard

NameError: name 'PythonCard' is not defined

import PythonCard

print PythonCard

print PythonCard.model

### 输出 ###

Traceback (most recent call last):

File "test.py", line 4, in

print PythonCard.model

AttributeError: 'module' object has no attribute 'model'

Python 之所以能 import package,是因为在 package 的目录下有个 __init__.py 文件,它表明了这个目录的 package 身份。(py3.3 以上不需要此文件)

我猜想 import PythonCard 是将 __init__.py 的 namespace 并入了当前文件的 namespace,而 from PythonCard import model 直接引入了 model 这个 module。

我又试了一下

from PythonCard.model import WidgetDict

print WidgetDict

### 输出 ###

PythonCard.model.WidgetDict

import PythonCard.model

print PythonCard.model

### 输出 ###

这表明 from 和 import 后既可以是 package 又可以是 module。(想想也是,要是不支持,岂不是麻烦死了)

修复错误

试了这么多,那为什么 import PythonCard 后没法调用 PythonCard.model 呢?还是要回到 namespace 上来,我尝试修改 __init__.py 文件。

"""

Created: 2001/08/05

Purpose: Turn PythonCard into a package

__version__ = "$Revision: 1.1.1.1 $"

__date__ = "$Date: 2001/08/06 19:53:11 $"

"""

# 我添加的

import model

添加了 import model 之后

import PythonCard

print PythonCard

print PythonCard.model

### 输出 ###

这样就可以修复上面代码的运行错误了,既然在 __init__.py 这个 namespace 中没有 model,那么我们只要引入就可以了。(但是,既然作者没有支持这种引入方式,如果你依然这样引入,可能需要不停地添加,不如直接引入 module,避免链式调用失败)

参考资料

接下来我在官方文档及网络上查阅资料,在模块这一章发现了这些

sound/ Top-level package

__init__.py Initialize the sound package

formats/ Subpackage for file format conversions

__init__.py

wavread.py

wavwrite.py

aiffread.py

aiffwrite.py

auread.py

auwrite.py

...

import sound.effects.echo

# This loads the submodule sound.effects.echo. It must be referenced with its full name.

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

# An alternative way of importing the submodule is:

from sound.effects import echo

# This also loads the submodule echo, and makes it available without its package prefix, so it can be used as follows:

echo.echofilter(input, output, delay=0.7, atten=4)

# Yet another variation is to import the desired function or variable directly:

from sound.effects.echo import echofilter

# Again, this loads the submodule echo, but this makes its function echofilter() directly available:

echofilter(input, output, delay=0.7, atten=4)

这几种是当 __init__.py 无内容时,正确的引入方式。

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

__init__.py 可以没有内容,但也可以为 package 执行一些初始化操作,它还拥有一个 __all__ 变量。初始化操作我在上头已经验证过,不再重复,但这个变量是干嘛的?

再看文档的下面一段

if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered.

当你在 __init__.py 中定义了 __all__ 时,如果你 from package import * ,那么这时会引入你指定的几个 module。

测试一下,未指定模块时

from PythonCard import *

print model

### 输出 ###

Traceback (most recent call last):

File "test.py", line 6, in

print model

NameError: name 'model' is not defined

指定模块时

"""

Created: 2001/08/05

Purpose: Turn PythonCard into a package

__version__ = "$Revision: 1.1.1.1 $"

__date__ = "$Date: 2001/08/06 19:53:11 $"

"""

# import model

__all__ = ["model"]

测试一下能否成功引入

from PythonCard import *

print model

### 输出 ###

import statement

我在这里还看到了引入语句的语法和详细执行过程,内容略多,我还没去理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值