在看库或框架的开源源代码时经常看到 __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。这些方法我们再熟悉不过。