Python 从文件导入特定类而不是从完整文件导入是否重要?
大多数关于Django或Flask的教程和书籍都从文件中导入特定类,而不是导入整个文件。Python 从文件导入特定类而不是从完整文件导入是否重要?,python,import,Python,Import,大多数关于Django或Flask的教程和书籍都从文件中导入特定类,而不是导入整个文件。 例如,从wrtforms.validators导入datarequired验证程序是通过从wtforms导入验证程序来完成的,而不是通过导入wtforms.validators作为valids导入,然后使用valids.datarequired访问datarequired 我的问题是:这有什么原因吗? 我想避免为计算/内存优化加载整个模块(这真的相关吗?)?还是仅仅为了使代码更具可读性?这取决于教程中可
例如,从
wrtforms.validators
导入datarequired
验证程序是通过从wtforms导入验证程序来完成的,而不是通过导入wtforms.validators作为valids
导入,然后使用valids.datarequired
访问datarequired
我的问题是:这有什么原因吗?
我想避免为计算/内存优化加载整个模块(这真的相关吗?)?还是仅仅为了使代码更具可读性?
这取决于教程中可能是为了可读性而做的
通常,如果使用文件中的大多数类,则导入文件。如果文件包含许多类,但您只需要几个,只需导入这些类即可。
这是一个可读性和优化的问题
我的问题是:这有什么原因吗
from module_或_package import something
是典型的pythonic习惯用法(当然,当您只想在当前名称空间中导入something
时)
另外,导入模块或包。只有当模块或包
是一个包而某事物
是一个子模块时,它才会引发一个导入错误(没有模块命名)
如果某事物
是一个函数、类或模块或包
中定义的任何对象,从stdlib中可以看出,os.path
(它是os.package
的子模块)与datetime.date
(它是在datetime
模块中定义的类):
只是语法上的糖分
import module_or_package
something = module_or_package.something
del module_or_package
import module
obj = module.obj
del module
编辑:你在评论中提到
是的,但是导入整个模块意味着将其加载到内存中,这可能是只导入子模块/类的原因
因此,我似乎没有明确说明这一点:在Python中,您不能“仅导入子模块/类”
在Python中,import
、class
和def
都是可执行语句(实际上只是语法糖,可以通过函数和类“手动”进行操作)。导入模块实际上包括执行模块顶层的所有代码(将实例化函数
和类
对象),并创建模块
对象(模块
类型的实例),这些属性将是通过导入
在顶层定义的所有名称,def
和class
语句或通过显式赋值。只有当所有这些都完成后,您才能访问模块中定义的任何名称,这就是为什么,正如我前面所述
from module import obj
只是语法上的糖分
import module_or_package
something = module_or_package.something
del module_or_package
import module
obj = module.obj
del module
但是(除非你做了一些愚蠢的事情,比如在你的模块中定义一个TB级的大目录或列表),这实际上并不需要那么多时间,也不会消耗太多内存,而且一个模块在第一次导入时每个进程只有效执行一次,然后它被缓存在sys.modules
中,所以后续的导入只会从缓存中获取它
此外,除非您主动阻止它,否则Python将缓存模块的编译版本(.pyc文件),并且只有在.pyc文件丢失或比源.py文件旧时才重新编译它
wrt/packages and submodules,导入子模块还将执行包的\uuuu init\uuuu.py
,并从中构建模块
实例(在运行时,包也是模块
)。包初始值设定项通常很短,实际上经常是空的FWIW…@VaibhavVishal我完全同意star导入是不好的,但我不明白这与问题有什么关系…对,但导入整个模块意味着将其加载到内存中,这可能是只导入子模块/类的原因。@Alakazam如前所述,“从模块导入给定名称需要导入整个模块”-cf我编辑的答案了解更多详细信息…我理解,但您正在删除模块后面的其余部分。加载大量模块可能会带来内存问题(即使我认为加载模块不会导致内存过大,理论上它可以)。@Alakasam我不是在“删除模块的其余部分”-del
语句只会删除名称(变量)和对象之间的绑定,它本身不会“删除”(以前)绑定的对象。仅当对象的refcount为null时,才会收集该对象,并且由于导入的模块缓存在sys.modules
中,因此该语句之后refcount将保持正值。您可能想阅读关于python中的名称和绑定的内容:感谢您的解释,如果del
只删除了绑定,那么请确保没有理由只导入一个类。我在很多django和flask项目中都看到了这一点,我只是觉得不可读,所以我想确定一下,通常你只想导入你需要的,以避免出现问题。但是,如果你从一个模块导入10个类中的9个,它会变得有点难看和不可读:我的问题是:会发生什么问题?覆盖类名称空间。假设您正在从两个不同的Views.py文件导入许多视图:您希望在第一次导入时使用“ExampleView”,但在第二次导入时,您还有一个“ExampleView”,它以不同的方式工作(但您不知道,因为您是盲目导入所有内容)。会发生的情况是,第二次导入“ExampleView”会覆盖第一次导入,您可能会损失很多时间,然后才能弄清楚为什么它不能按预期工作。当你在一个团队中处理相同的文件时,这一点尤其正确。你基本上说的是相反的。。当您从模块导入特定类时,可能会出现这些问题,我认为
import module
obj = module.obj
del module