当前位置: 首页 > 科技观察

一篇文章看懂Python中的核心概念:import、module、package

时间:2023-03-14 16:04:40 科技观察

本文转载自微信公众号《Python社》,作者黄伟AI。转载本文请联系Python学会公众号。前言Python作为一个解释器,一个程序,如果不导入任何外部模块或包就不能做很多事情。了解Python如何导入模块和包将对几乎所有场景都有帮助。本文中的所有代码都在Linux(Ubuntu)、Windows和macOS中应用和测试过(希望如此)。pip安装包时会发生什么当我们使用pip安装包时:pipinstallpackageintothesystem-widefolder/home//.local/lib/python3.x/site-packageshere"System-wide"意味着所有Python程序都可以访问已安装的包。在哪里导入(import)当使用import关键字导入一个包时,Python会循环遍历sys.path中的路径列表。从中加载它的路径。运行此命令以查看路径列表:importsysprint(sys.path)这是我的。你的应该看起来像:['','/usr/lib/python36.zip','/usr/lib/python3.6','/usr/lib/python3.6/lib-dynload','/home/andrewzhu/.local/lib/python3.6/site-packages','/usr/local/lib/python3.6/dist-packages','/usr/lib/python3/dist-packages','/usr/lib/python3.6/dist-packages']第一个空的"表示当前文件夹,因此Python运行时(或import关键字)可以访问位于运行Python脚本的同一文件夹中的任何包。通过理解这一点,下次如果你想部署自定义包,而不是从pip或condo。你从Github窃取/抓取一些东西,并想让所有Python程序都可以访问它,无论它位于何处。你知道把包放在Where。顺便说一句,要获取当前目录路径,请运行:importosprint(os.getcwd())导入模块的最佳方式是什么正如Python之禅所说:“显式优于隐式”。如果你在几周后命名像i、td这样的变量,即使是你,这个程序的作者,也不会理解这些变量的含义。所以,规则1:要清楚。Python作为一种脚本语言已经比较慢了,为了让你的程序更快,需要加载模块。规则2:只需要导入。如果您编写的程序可能会被其他程序调用,请注意命名冲突。其他人可能会在下游程序中被赋予相同的名称,并且可能会收到“类型错误异常”。规则3:获得正确的名称。您可能会看到下面列出的许多导入样式,但哪一种是最好的,哪一种应该避免呢?#style1importa_package#orstyle2importa_packageasp#orstyle3froma_packageimporta_item#orstyle4froma_packageimport*#orstyle5froma_packageimporta_itemasmy_itemstyle1可以,但是它会导入这个包中的所有模块,以防datetime被导入。当你想获取当前时间时,代码是这样构成的:importdatetimenow_time=datetime.datetime.now()注意,有两个datetimes,如果你正在阅读一个长代码文件,每当你看到datetime,就会让你想想它是哪个日期时间,它是一个模块还是一个包?Style2会在一定程度上解决这个问题,你可以给datetime起一个新的名字,也许是唯一的名字,像这样:.然而,每次都输入包名是很乏味的。样式3解决了繁琐的问题,通过导入from...样式,可以直接调用函数。fromdatetimeimportdatetimenow_time=datetime.now()如果您想尽量减少命名冲突,请使用样式5。fromdatetimeimportdatetimeaspkg_datetime_modulenow_time=pkg_datetime_module.now()风格4?永远不要使用import*风格。因为样式4打破了上面列出的3个规则。如果你打算构建一个包供其他人使用,有一种方法可以减少import*事故。使用__all__。这是一个例子。在你的模块中。__all__=['pub_fun1','pub_fun2']defpub_fun1:return'hey,thisispub_function1'defpub_fun2:return'hey,thisispub_function2'defpub_fun3:return'sorry,thisfunctionisprivate'这样,即使模块用户通过import*调用你的包,只有pub_fun1和pub_fun2会被通配符导入。Pub_fun3会对调用者保密。如果你的同事顽固地坚持使用import*,你可以通过下面他们import*的True和False颠倒来说服他们:False,True=True,False#worksonlyinpython2.xPython会颠倒True和False的意思,就是这个原因为什么我们在命名和导入模块时需要小心。检查导入的模块当你导入一个模块时,你怎么知道它里面有什么?当然,您可以查看文档,但是如果您懒惰并且不想启动无聊的文档怎么办?Python在这一点上提供了一种方便的方法来执行此操作。它是函数dir()。此内置函数返回目标对象的一级名称列表。假设您导入了数学模块。importmath查看数学模块中有哪些函数。dir(math)您将看到可供调用的变量和函数列表。现在运行不带参数的dir()函数以查看当前模块中包含的内容。dir()你会在结果列表中看到importedmath[...,math,...]还有一点,如果你想删除一个现有的模块,你可以使用del来删除它。在这里,让我们从当前运行的程序中删除数学。delmath检查dir()并且数学消失了。创建自己的Python包在Python中,Function是变量和表达式的容器;类是函数和变量的容器;Module大致代表一个Python脚本文件,是类、函数、表达式、变量的容器。包是用于管理Python模块的解决方案。包是一个特殊的文件夹,其中包含多个模块和一个额外的__init__.py文件。下面是一个示例包结构。如果使用Python3.3+,则可以省略__init__.py文件py_package/-__init__.py-module1.py-module2.py在py_package文件夹内,创建两个名为module1.py和module2.py的文件。在module1.py文件中,提供以下代码,并在module2.py文件中,放入您喜欢的任何代码。#module1.pyfile__all__=["module1_pub_func"]defmodule1_pub_func():print('hey,thisisapublicfunctionfrommodule1')defmodule1_pri_func():print("hey,thisisaprivatefunctionfrommodule1")现在,在py_package文件夹所在的同一文件夹中,放置test.py文件。-py_package/-...-test.pytest.py文件中,调用新烘焙的包。frompy_package.module1import*module1_pub_func()module1_pri_func()你会得到这个,这里的错误信息是预期的,因为在你的__all__变量中你只允许调用pubfunc。嘿,thisisapublicfunctionfrommodule1----------------------------------------------------------------------NameErrorTraceback(mostrecentcalllast)~/az_git_folder/azcode/aznote/python/py_create_package/test.pyin2frompy_package.module1import*3module1_pub_func()---->4module1_pri_func()NameError:name'module1_pri_func'isnotdefined请注意,使用下面显示的代码导入包不起作用。谷歌不会告诉你太多,但如果你不知道这个错误,它可能会让你困惑一段时间。#importthenewcreatedpackagewon'tworks.don'tdoit.importpy_packageimport*#orimportpy_package要调用此包,您需要明确包含module1关键字。还有一件事要提。每个Python模块/程序都定义了一个__name__变量。如果模块/程序是Python执行的入口点,__name__将被分配给“__main__”。因此,我们可以使用__name__来检测一个程序是直接执行的还是从另一个程序导入的。在设计自定义包时特别有用。if__name__=='__main__':print('runningbymyself')else:print('Iambeingimportedfromothermodule')