想象一个具有以下结构的包:
└── main_package
├── __init__.py
├── subpackage1
│ ├── __init__.py
│ └── module1.py
└── subpackage2
├── __init__.py
└── module2.py
将module1
中的函数导入module2
的最佳方式是什么?
__init__.py
文件应该包含什么吗?
我找到的最好的解决方案是包含在module2
中
import sys
sys.path.append('./')
from main_package.subpackage1.module1 import fun1
当从main_package
所在的目录运行module2
时,它起作用。
但我觉得这并没有利用它们是包裹的事实。如果可能的话,能在任何我想的地方运行它也会很好。
最可靠的方法是始终使用绝对导入。在这种情况下,对于模块1:
from MainPackage.module2 import some_function
在module1_1
中,这将是:
from MainPackage.Subpackage2.module2_1 import some_function
请注意,包命名约定是使用所有小写字母,并且在单词之间可以使用下划线(_
)。在您的特定示例中,MainPackage
将变为main_package
,依此类推
对于您的第一个问题:
将模块1中的函数导入模块2的最佳方式是什么?
您可以使用相对导入或绝对导入。就我个人而言,我更喜欢在我正在处理的包的上下文中只使用相对导入——对我来说,这突出了内部包是相关的。此外(这是特定于环境的),在安装包之前,某些环境不会识别main_package
(即在开发过程中使用pip install -e .
)。
模块2:from main_package.subpackage1.module1 import my_function
中的绝对导入
模块2:from ..subpackage1.module1 import my_function
中的相对导入
对于您的第二个问题:
init.py文件应该包含什么吗?
它们可以,并且可能为您提供导入的快捷方式。在包级别公开通用和/或一流函数/类是一种常见的做法,本质上只是在__init__.py
中导入它们
例如,在subpackage1__init__.py
中,您可以:
from .module1 import my_function
然后在subpackage2module2.py
中,您可以简单地使用from ..subpackage1 import my_function
(相对导入)或from main_package.subpackage1 import my_function
。
您可能还对原始Python文档中的主题感兴趣-导入/子模块、从包导入*(用于对导入系统的额外阅读,然后是包内导入)、PEP328(相对导入的基本原理)以及Guido关于相对导入的想法。
观看视频后https://youtu.be/U2OcGe-qSEY,我想回到这个问题上来。嗯,你不需要太多。如果以后不打算单独使用子包1和2,那么这两个文件夹中甚至不需要__init__.py
文件。在我的旧答案中,您也不需要main.py
文件。您甚至不需要在主包的__init__.py
文件中编写任何内容,就可以在不同部分中调用该项目中文件的函数。您也可以避开module2.py
中的import sys; sys.path.append('./')
。您所需要的只是相对于主程序包的相对路径。所以在module2.py
的顶部可以写from ..subpackage1.module1 import fun1
。从左到右,我们首先看到一个双点,右边的第一个点表示查看包含该文件的文件夹,即subpackage2
,然后它后面的第二个点表示向上移动一个文件夹,所以现在我们在main_package
中,它表示转到subpackage1
,然后转到module1
,然后拾取同名的fun1
,所以在该文件中,您可以简单地调用fun1
。
现在,如果您在其他地方导入main_package,您就可以访问所有内容。当然,您必须调用带有中间子包的函数。如果你想把它们称为main_package
的直接财产,那么你可以把我旧答案的导入行放在主包的__init__.py
文件中,这样你就可以把它们叫做main_package.fun1
,而不是from main_package.subpackage1 import fun1
。
旧答案:
在Maple中,在模块的主文件中导入模块将自动与模块的其他文件和子模块共享。您还可以调用在同一模块的不同文件中定义的函数,只要您已将它们链接起来,只需在主文件中包含模块文件的地址即可。因此,您只需在一个文件中键入地址,而不需要将它们写入模块的其他文件中。在我看来,这会让生活变得更轻松。
在Python中,我不能像在Maple中那样做,以下是我在当前实践中所做的。让我解释一下玩具的例子。有一个文件夹包含一个python文件main.py
和您在问题中显示的包结构。每个文件的内容如下。
主.py
import main_package
main_package.fun2()
CCD_ 39的CCD_。
from .subpackage1.module1 import fun1
from .subpackage2.module2 import fun2
子包的两个init文件是空的。
模块1.py
import sympy
x = sympy.Symbol('x')
def fun1(polynomial):
return(sympy.degree(polynomial, gen = x))
模块2.py
import sympy
from ..subpackage1.module1 import fun1
def fun2():
polynomial = sympy.sympify(input("Type a univariate polynomial with the variable x and integer coefficients:"))
print(f"Degree of your polynomial in x is {fun1(polynomial)}.")
现在,我不再运行main_package
的__init__.py
,而是在VSCode中运行main.py
。注意,我的main.py文件在main_package文件夹旁边,而不是在它里面
同样,我认为必须在两个文件module1.py
和module2.py
中的每一个文件中写入import sympy
是令人难过的。我很感兴趣的是,如果有一天有人展示了一种方法,可以只在顶部父级__init__.py
中写入import sympy
和x = sympy.Symbol('x')
,而避免在两个文件module1.py
和module2.py
中写入。