在看库或框架的开源源代码时经常看到 __init__.py 里留下了若干代码。__init__.py 文件让python认为init所在的文件夹是一个包,这自不必详说。
当将一个包作为模块导入时,实际上导入了它的 __init__.py 文件。
当我们导入init包的时候,init脚本自动运行。
那么,为什么要在 __init__.py 文件里写代码,这样做有什么好处。
好处:在 __init__.py 里写一些程序内部用到的数据结构或为用户提供一个统一的接口。
例如:
以 django forms 模块为例,在django.forms 模块里定义了各种各样的函数和类,这些函数和类分类放在不同的文件中。
forms/
__init__.py
extras/
...
fields.py
forms.py
widgets.py
...
现在你要写一个新 form ,必须继承 Form 类,在 __init__.py 没发挥作用时的代码是这样的:
class CommentForm(forms.forms.Form):
name = forms.fields.CharField()
url = forms.fields.URLField()
comment = forms.fields.CharField(widget=forms.widgets.Textarea)
这样既不方便又很丑。而我们一般直接使用的是 django.forms 包下的 namespace。像这样:
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)
这就是在 forms/__init__.py 里写代码的好处(可以引入 widgets, forms, fields)
from django.forms.fields import *
from django.forms.forms import *
from django.forms.formsets import *
from django.forms.models import *
from django.forms.widgets import *
例2:
有这样一个foo包
foo/
__init__.py
foofactories.py
tallFoos.py
shortfoos.py
mediumfoos.py
santaslittlehelperfoo.py
superawsomefoo.py
anotherfoo.py
在init脚本里这样写:
__all__ = ['foofactories', 'tallFoos', 'shortfoos', 'medumfoos',
'santaslittlehelperfoo', 'superawsomefoo', 'anotherfoo']
# deprecated to keep older scripts who import this from breaking
from foo.foofactories import fooFactory
from foo.tallfoos import tallFoo
from foo.shortfoos import shortFoo
如此做,则可以在别的脚本里简单方便的写:
from foo import fooFactory, tallFoo, shortFoo
简化了代码量。
若 from foo import * ,则导入了init里的 __all__ 变量里注册的所有模块(不推荐)
Django 经常把一些共通的类或函数放在 init 里,例如 django.conf.urls 包中的init里定义了三个方法 include,patterns,url。这些方法我们再熟悉不过。