为什么要在 __init__.py 文件中放代码?

84 投票
3 回答
20237 浏览
提问于 2025-04-16 16:39

我想知道在 __init__.py 文件里应该写什么样的代码,还有一些相关的最佳实践是什么。或者说,这样做一般算不算坏习惯呢?

如果有一些相关的文档可以参考,那就太好了。

3 个回答

7
  1. 为了方便:其他用户不需要知道你函数的具体位置。

    your_package/
      __init__.py
      file1.py/
      file2.py/
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    这样其他人就可以通过

    from your_package import add
    

    来调用add(),而不需要知道file1,比如:

    from your_package.file1 import add
    
  2. 放一些初始化的内容。例如,记录日志(这应该放在最上面):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    
14

在这个领域,一个很好的做法是从你的库中导入所有需要的类(比如看看mongoengine)。这样,使用你库的用户可以这样做:

from coollibrary import OneClass, SecondClass

而不是这样:

from coollibrary.package import OneClass
from coollibrary.anotherpackage import SecondClass

另外,一个好的做法是在__init__.py文件中包含版本常量。

71

库和框架通常在 __init__.py 文件中使用初始化代码,这样可以把内部结构隐藏得很整齐,同时给用户提供一个统一的接口

我们以 Django 的表单模块 为例。这个表单模块里的各种函数和类是根据分类定义在不同的文件里的。

forms/
  __init__.py
  extras/
    ...
  fields.py
  forms.py
  widgets.py
  ...

如果你想创建一个表单,你就得知道每个函数在哪个文件里,这样你创建一个联系表单的代码可能会像这样(这很麻烦,也不美观)。

 class CommentForm(forms.forms.Form):
    name = forms.fields.CharField() 
    url = forms.fields.URLField()
    comment = forms.fields.CharField(widget=forms.widgets.Textarea) 

但在 Django 中,你可以直接从表单的命名空间引用各种小部件、表单、字段等等。

from django import forms

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField(widget=forms.Textarea)

这怎么做到的呢?为了实现这一点,Django 在 forms/__init__.py 文件中添加了以下语句,这样就把所有的小部件、表单、字段等都导入到了 forms 的命名空间里。

from widgets import *
from fields import *
from forms import *
from models import *

如你所见,这样在创建表单时就简单多了,因为你不需要担心每个函数或类是在哪个地方定义的,只需直接从 forms 的命名空间使用它们。这只是一个例子,但在其他框架和库中也能看到类似的情况。

撰写回答