![机械工程师Python编程:入门、实战与进阶](https://wfqqreader-1252317822.image.myqcloud.com/cover/439/51753439/b_51753439.jpg)
1.3 导入代码
假设你有一段Python代码,需要在多个文件中使用。方法之一是,在每次需要该代码时,都进行复制和粘贴。这不仅费时而无聊,而且如果你想对代码做一些改动,则需要打开每一个粘贴有这段代码的文件,然后以同样的方式修改它。可想而知,这样编写软件的效率不高。
幸运的是,Python提供了一个共享代码的强大功能:模块导入。当模块b导入模块a时,模块b可以访问模块a中的代码。这使我们可以在某处编写程序,然后跨文件共享。让我们以本书第二部分将要编写的两个模块为例。
假设有两个模块:point.py和vector.py。这两个模块都在前面提到的包中:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/34_01.jpg?sign=1734533987-ZVLqQQBUId0Gvn21XGoPevGmwjAMxjYD-0-a6329f690b22194e1f36879d3c07e630)
第一个模块point.py定义了几何基元——点,第二个模块vector.py定义了另一个几何基元——向量。图1-1是两个模块的图示。每个模块都分为两个部分:灰色区域代表从其他地方导入的代码,白色区域代表模块自身定义的代码。
现在,假设point.py模块的某些功能需要使用向量(例如,使用向量移动某个点),我们可以使用Python的import命令访问vector.py中的向量代码。图1-2描绘了这个过程,Python将向量代码带到point.py的“导入区”,使它在模块内部可以被使用。
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/34_02.jpg?sign=1734533987-3qC5u4J1u5a1lKPxDYMMpf89smlpfsJq-0-7faab4c04582ec1a03e61a38c48a88ef)
图1-1 两个Python模块
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/34_03.jpg?sign=1734533987-iWJpZ2KbDKHBlMDSEX6wx14IP5qfJ49a-0-fba6b6c181beee00e53d4a2c0b0de92a)
图1-2 从vector.py导入Vector类
在图1-2中,我们使用了如下Python命令:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/34_04.jpg?sign=1734533987-tWvCvXpaeEyqnZAZ0Ji6iT7Ew77zpNm5-0-b80f91fa340a4498e1c25dbf5f72559c)
这个命令只从vector.py中获取Vector类,不会导入其他任何东西。
下面将会介绍几种模块导入方法。
不同的导入形式
为了理解导入模块和模块内实体的不同方法,我们需要使用Mechanics项目的两个包:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/34_05.jpg?sign=1734533987-EFciWkALvK6efvQoIntpzRjYRInnxQSH-0-e7c1dc2d58651f85e7459e442adfe6d3)
在本例中,我们会使用geom2d和eqs包的各两个文件,或者模块。每个模块都定义了一个与模块同名的类,类名的首字母大写。例如,point.py模块定义了Point类,vector.py模块定义了Vector类,matrix.py模块定义了Matrix类。图1-3展示了包的结构。
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_01.jpg?sign=1734533987-vOkYH2g5vscxekDLsNAnT8NtMCnLLhca-0-3765b99a8c4143dd2abece241428e1b1)
图1-3 Mechanics项目中的两个包和它们的部分模块
记住这个目录结构,让我们分析几个场景。
(1)导入同一个包的模块
在geom2d包的point.py模块中,如果想导入整个vector.py模块,我们可以使用以下方法:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_02.jpg?sign=1734533987-Yo8IkXMz9RwAqG8ZO8Wt61Vz9b8z0oA4-0-07f90399852c03054b0d8083290acc11)
这样我们就可以使用vector.py中的内容,如下所示:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_03.jpg?sign=1734533987-tzBQVUjGKjN5Mr1F5IeBAqdJXqlqz2jq-0-a33ff6957b7bceabf1ba1e77eca5ba8c)
请注意,由于我们导入的是整个模块,而不是它的某个实体,因此我们必须用模块名称来指向该模块中定义的实体。如果想给被引用的模块一个不同的名称,我们可以给它重命名:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_04.jpg?sign=1734533987-CoBjiiVRklsvGiiA0fPidrSzsIXBBmVz-0-60e2d11ce3ca218c76f3686ffc1c07a2)
然后可以这样使用它:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_05.jpg?sign=1734533987-Pn490ajOdqIeo5rO83tKItcn3ti7G4QH-0-f08ff9c7747abd4695eca17ab9882e57)
我们还可以从模块中导入特定的名称,而不是整个模块。正如你前面所看到的,它的语法如下:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_06.jpg?sign=1734533987-hIhTd76aFxqp8q0M9N1mWg60qh9XhT3z-0-8f2f6741071ab76dd92566099860c04f)
使用这种导入方式,我们可以执行如下操作:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_07.jpg?sign=1734533987-lBc8kFSEBkN5bwThe6G8Uqk0ku7ZjbCH-0-c227dee6e579a823454c1904d85e3e35)
在这种情况下,我们还可以重命名导入的名称:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_08.jpg?sign=1734533987-UmbbqGnIH5oQdRBaOWiMTJw2xMEsxBrm-0-0d310fc6c15a2b536170a79f4150e043)
当我们为一个导入的名称起别名时,我们只需将其重命名为其他名称。在本例中,代码可以写成如下形式:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/35_09.jpg?sign=1734533987-Xut6xkcjV24pSUwtMtB51dGECk7tN0VO-0-6dcebdd79828b1b85be4dd6d1a0eb19c)
(2)导入不同包的模块
如果想在matrix.py模块中导入point.py模块,那么由于point.py在不同的包中,我们可以如下操作:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_01.jpg?sign=1734533987-kAx0NobYA1nmePD7cbiF41S4nwjdnpPj-0-c4d6f4d984357549a4649a00fc13ab52)
或者
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_02.jpg?sign=1734533987-HDLIygMx2VgwZzjl4vLWtFjZkc2eKkzw-0-d893d11dc29d2bb9599eed854f24faba)
这让我们可以在matrix.py中使用point.py模块的全部内容:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_03.jpg?sign=1734533987-ApQxJxrREwsNEJoyBIHxmmaEiCSSBWZ8-0-86097fa85e0b69d39719f6750de5de22)
同样,我们可以对导入的模块重命名:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_04.jpg?sign=1734533987-7Cpcxzu0mfTh6YpWIHRxK1wUQaAhrLRo-0-4200f7b192419c499a9895e92dd5c60d)
或者,等价地:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_05.jpg?sign=1734533987-Mb0698SdG0yfwH03LXFcEyl27qA3VboA-0-d64ef1bb091c4832ef67343f93ed66dc)
用这两种方式,我们都可以使用pt如下:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_06.jpg?sign=1734533987-kLGQcexiAHAA24dDhIYFry5DNDSxsNPl-0-8264d975a9ab78365ec5e2e304f519cf)
我们还可以从模块中导入特定的名称,而不是整个模块,如下所示:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_07.jpg?sign=1734533987-Z5iUrMhxQnUrutAmfA9t3gGYOapYrz3p-0-20c321ce9ccf18fdec0e8df9b5e7813f)
与前面一样,我们可以使用一个别名:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_08.jpg?sign=1734533987-dvwiNLHZeylWCGFgEbkl4D1dS0DsLYiS-0-c71238757c677b534c4230dd442c5b56)
(3)相对导入
最后是相对导入。相对导入(relative import)是指导入模块所使用的路径是相对路径,其起点是文件的当前位置。
我们用一个点(.)指代同一个包内的模块或包,用两点(..)指代该包的父级目录。
同样是前面的例子,我们可以使用相对导入在matrix.py内导入point.py模块:
![](https://epubservercos.yuewen.com/AE06E7/30549606304263306/epubprivate/OEBPS/Images/36_09.jpg?sign=1734533987-lXAh2HBEJCtMHCVohqVM4GTGQnBbZYMA-0-cb3c7ecf92a9f81edbd7720427de196e)
上述代码中,路径..geom.point的含义是:从当前的目录移动到父级目录,然后定位point.py模块。