1. 程式人生 > >在 __init__.py 裡寫程式碼的若干理由

在 __init__.py 裡寫程式碼的若干理由

在看庫或框架的開源原始碼時經常看到 __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。這些方法我們再熟悉不過。