Skip to content

10.4小节完成 #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 19, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 25 additions & 39 deletions source/c10/p04_split_module_into_multiple_files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
----------
问题
----------
You have a module that you would like to split into multiple files. However, you would
like to do it without breaking existing code by keeping the separate files unified as a
single logical module.
你想将一个模块分割成多个文件。但是你不想将分离的文件统一成一个逻辑模块时使已有的代码遭到破坏。


|

----------
解决方案
----------
A program module can be split into separate files by turning it into a package. Consider
the following simple module:
程序模块可以通过变成包来分割成多个独立的文件。考虑下下面简单的模块:


.. code-block:: python

Expand All @@ -28,9 +27,9 @@ the following simple module:
def bar(self):
print('B.bar')

Suppose you want to split mymodule.py into two files, one for each class definition. To
do that, start by replacing the mymodule.py file with a directory called mymodule. In
that directory, create the following files:
假设你想mymodule.py分为两个文件,每个定义的一个类。要做到这一点,首先用mymodule目录来替换文件mymodule.py。
这这个目录下,创建以下文件:


.. code-block:: python

Expand All @@ -39,7 +38,7 @@ that directory, create the following files:
a.py
b.py

In the a.py file, put this code:
在a.py文件中插入以下代码:

.. code-block:: python

Expand All @@ -48,7 +47,7 @@ In the a.py file, put this code:
def spam(self):
print('A.spam')

In the b.py file, put this code:
在b.py文件中插入以下代码:

.. code-block:: python

Expand All @@ -58,16 +57,15 @@ In the b.py file, put this code:
def bar(self):
print('B.bar')

Finally, in the __init__.py file, glue the two files together:
最后,在 __init__.py 中,将2个文件粘合在一起:

.. code-block:: python

# __init__.py
from .a import A
from .b import B

If you follow these steps, the resulting mymodule package will appear to be a single logical
module:
如果按照这些步骤,所产生的包MyModule将作为一个单一的逻辑模块:

.. code-block:: python

Expand All @@ -85,44 +83,34 @@ module:
----------
讨论
----------
The primary concern in this recipe is a design question of whether or not you want
users to work with a lot of small modules or just a single module. For example, in a large
code base, you could just break everything up into separate files and make users use a
lot of import statements like this:
在这个章节中的主要问题是一个设计问题,不管你是否希望用户使用很多小模块或只是一个模块。举个例子,在一个大型的代码库中,你可以将这一切都分割成独立的文件,让用户使用大量的import语句,就像这样:


.. code-block:: python

from mymodule.a import A
from mymodule.b import B
...

This works, but it places more of a burden on the user to know where the different parts
are located. Often, it’s just easier to unify things and allow a single import like this:
这样能工作,但这让用户承受更多的负担,用户要知道不同的部分位于何处。通常情况下,将这些统一起来,使用一条import将更加容易,就像这样:


.. code-block:: python

from mymodule import A, B

For this latter case, it’s most common to think of mymodule as being one large source
file. However, this recipe shows how to stitch multiple files together into a single logical
namespace. The key to doing this is to create a package directory and to use the
__init__.py file to glue the parts together.
对后者而言,让mymodule成为一个大的源文件是最常见的。但是,这一章节展示了如何合并多个文件合并成一个单一的逻辑命名空间。
这样做的关键是创建一个包目录,使用 __init__.py 文件来将每部分粘合在一起。


When a module gets split, you’ll need to pay careful attention to cross-filename references.
For instance, in this recipe, class B needs to access class A as a base class. A packagerelative
import from .a import A is used to get it.
当一个模块被分割,你需要特别注意交叉引用的文件名。举个例子,在这一章节中,B类需要访问A类作为基类。用包的相对导入 from .a import A 来获取。


Package-relative imports are used throughout the recipe to avoid hardcoding the toplevel
module name into the source code. This makes it easier to rename the module or
move it around elsewhere later (see Recipe 10.3).
整个章节都使用包的相对导入来避免将顶层模块名硬编码到源代码中。这使得重命名模块或者将它移动到别的位置更容易。(见10.3小节)


One extension of this recipe involves the introduction of “lazy” imports. As shown, the
__init__.py file imports all of the required subcomponents all at once. However, for a
very large module, perhaps you only want to load components as they are needed. To
do that, here is a slight variation of __init__.py:
作为这一章节的延伸,将介绍延迟导入。如图所示,__init__.py文件一次导入所有必需的组件的。但是对于一个很大的模块,可能你只想组件在需要时被加载。
要做到这一点,__init__.py有细微的变化:

.. code-block:: python

Expand All @@ -135,8 +123,8 @@ do that, here is a slight variation of __init__.py:
from .b import B
return B()

In this version, classes A and B have been replaced by functions that load the desired
classes when they are first accessed. To a user, it won’t look much different. For example:
在这个版本中,类A和类B被替换为在第一次访问时加载所需的类的函数。对于用户,这看起来不会有太大的不同。
例如:

.. code-block:: python

Expand All @@ -146,8 +134,7 @@ classes when they are first accessed. To a user, it won’t look much different.
A.spam
>>>

The main downside of lazy loading is that inheritance and type checking might break.
For example, you might have to change your code slightly:
延迟加载的主要缺点是继承和类型检查可能会中断。你可能会稍微改变你的代码,例如:

.. code-block:: python

Expand All @@ -157,7 +144,6 @@ For example, you might have to change your code slightly:
if isinstance(x, mymodule.a.A): # Ok
...

For a real-world example of lazy loading, look at the source code for multiprocessing/
__init__.py in the standard library.
延迟加载的真实例子, 见标准库 multiprocessing/__init__.py 的源码.