python 模块定义、导入、优化

模块:

在Python中,一个.py文件就称之为一个模块(Module)。

它是实现了某个功能的代码集合。

模块分为三种:

1.自定义模块

2.内置标准模块(又称标准库)

3.开源模块

模块导入方法:

1. import module_name (导入一个模块)

2. import module_name,module2_name (导入多个模块)

3. from module_name import * (不推荐使用)

4. from module_name import m1 as name_m1 (导入指定的函数或变量并重命名)

5. from module_name import m1,m2,m3 (导入模块的多个函数或变量)

第3种办法,不推荐使用。因为这一段话,相当于把module_name.py的所有代码复制到当前代码中,调用的时候,直接写方法名调用,不需要module_name.方法名()这种方式调用。如果发现方法名或者变量冲突,以本代码为准。

import的本质

把导入模块的所有代码解释一遍,统一赋值给一个变量,这个变量名叫模块名。

调用变量,使用 module_name.变量名

调用函数,使用 module_name.函数名()

from的本质

把导入模块的指定函数或者变量,放到当前文件的位置,执行一遍。

调用变量或者函数的时候,直接使用即可,不需要在前面加模块名。

自定义一个模块

新建文件hello.py

name = "zhang"
def say_hello():
    print("hello,",name)

新建文件test.py,导入模块。注意,模块名是去除.py之后的名字

import hello
#输出变量,执行方法
print(hello.name)
hello.say_hello()

执行输出

zhang

hello, zhang

包:

用来从逻辑上组织模块,本质就是一个目录(必须带有一个__init__.py文件)

导入包的本质:

去执行包目录下的__init__.py文件

使用pycharm编辑器,新建一个包package_test

编辑__init__.py文件

print('from the package package_test')

新建一个文件p_test.py

import package_test

目录结构如下:

.
├── p_test.py
└── package_test
    └── __init__.py

执行p_test.py,输出

from the package package_test

上面介绍的模块导入,都是基于同级目录的。那么module在不同目录下,该如何导入呢?

目录结构如下:

.
├── hello.py
└── package_test
    ├── __init__.py
    └── main.py

main.py需要导入hello模块

先来分析一个导入模块的执行步骤

import module_name->找到module_name.py文件->找到module_name.py的路径->sys.path(搜索路径)

编辑main.py,打印sys.path

import sys
print(sys.path)

使用cmd执行,执行输出

['E:\\python_script\\day5\\package_test', 'C:\\Program Files\\Python36\\python36.zip', 'C:\\Program Files\\Python36\\DLLs', 'C:\\Program Files\\Python36\\lib', 'C:\

\Program Files\\Python36', 'C:\\Program Files\\Python36\\lib\\site-packages']

第一个元素,就是当前路径

如果一个元素找不到,就会找下一个元素,直到所有的目录都还找不到的话,就报错

ModuleNotFoundError: No module named 'xxx'

为了解决这个问题,需要加一个路径,必须要包含需要导入模块的路径。这个路径,一般为项目根目录。

编辑main.py,先来打印当前文件的绝对路径

import sys,os
print(os.path.abspath(__file__))

执行输出

E:\python_script\day5\package_test\main.py

然后获取当前目录

import sys,os
print(os.path.dirname(os.path.abspath(__file__)))

执行输出

E:\python_script\day5\package_test

最后获取上一层目录,定义变量

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_DIR)

执行输出

E:\python_script\day5

这个目录,就可以找到package_test路径了!

将项目根目录添加到系统环境变量中

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

最后导入模块,执行函数

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

import hello

hello.say_hello()

执行输出

hello, zhang

注意:

sys.path.append(BASE_DIR) 是将项目根目录追加到最后一个列表元素。如果中间某一个元素,正好找到了指定文件,比如hello.py,那么就不会再查找后面的路径了,直接加载。

如果出现了这种情况,必须要把BASE_DIR插入到第一个元素位置,使用insert方法

sys.path.insert(0,BASE_DIR)
print(sys.path)

执行输出

['E:\\python_script\\day5', 'E:\\python_script\\day5\\package_test', 'E:\\python_script', 'C:\\Program Files\\Python36\\python36.zip', 'C:\\Program Files\\Python36\\DLLs', 'C:\\Program Files\\Python36\\lib', 'C:\\Program Files\\Python36', 'C:\\Program Files\\Python36\\lib\\site-packages']

举另外一个例子

main.py需要调用test1.py里面的函数,目录结果如下:

.
├── module_test
│   └── main.py
└── package_test
    ├── __init__.py
    └── test1.py

test1.py内容如下:

def test():
    print('in the test1')

main.py直接引用package_test包,是否可以执行呢?

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

import package_test

package_test.test1.test()

执行报错

ModuleNotFoundError: No module named 'test1'

因为import package_test 这一步是执行package_test目录下的__init__.py文件,而这个文件是空的

修改__init__.py文件,从当前目录下,导入test1模块

这个 点 表示相对于__init__.py文件的路径。

from . import test1

再次执行main.py

执行输出

in the test1

再深层次的目录调用,目录结果如下:

python_script/
├── day4
│   └── test.py
└── day5
    └── package_test
        ├── __init__.py
        └── test1.py

day5的代码,同上,没改动

test.py需要调用test1.py,那么需要把python_script目录加到环境变量即可

修改day4下的test.py文件

import sys,os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(BASE_DIR)

执行输出

E:\python_script

加载到环境变量

import sys,os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

from day5 import package_test
package_test.test1.test()

执行输出

in the test1

注意下面这行代码

from day5 import package_test

day5表示python_script目录下的day5

导入优化

语法:

from 模块名 import 函数或变量名

举个例子,目录结构如下:

test4/
├── module_test.py
└── test.py

module_test.py内容如下:

def test():
    print('in the test')

test.py内容如下:

import module_test

def logger():
    module_test.test()
    print('in the logger')

def search():
    module_test.test()
    print('in the search')

#假设有N个函数在调用module_test.test()
#...
logger()

执行输出

in the test

in the logger

module_test.test()在执行的时候,先找到module_test模块,再从里面检索test函数是否存在。

那么每执行一次,就要先找模块,再找函数,重复劳动,效率很低。

为了解决这个问题,就是在导入模块的时候,不让它找就可以了

import module_test

改成

from module_test import test

就可以了。

下面的执行方法module_test.test()改成test() 就可以了,完整代码如下

#!/usr/bin/env python
# coding: utf-8
__author__ = 'www.py3study.com'

from module_test import test

def logger():
    test()
    print('in the logger')

def search():
    test()
    print('in the search')

#....

logger()

执行输出

in the test

in the logger

这种方法,可以使代码执行的更快

为了避免函数重名,可以在导入的时候,起别名

from module_test import test as mod_test

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏锦小年的博客

python学习笔记5.3-包的创建

包,也可以称为库,是具有很多功能的一个集合体。本文主要介绍如何自己创建一个包,以及介绍一些在包的创建过程中的技巧。 1. 包的创建 本文的例子将使用最复杂的情况...

2678
来自专栏IT杂记

Zookeeper笔记一:session

Chroot特性 从3.2.0版本开始可通过connection String后面跟上一个绝对路径设置root,比如“192.168.1.1:2181/app/...

2006
来自专栏有趣的django

12.python进程\协程\异步IO

进程 Python中的多线程无法利用多核优势 , 所以如果我们想要充分地使用多核CPU的资源 , 那么就只能靠多进程了 multiprocessing模块中提供...

3948
来自专栏海天一树

小朋友学Python(27):全局变量的引用和修改

一、引用 例1 a = 1 def func(): if 1 == a: print("a = %d" % a) if __name__...

2867
来自专栏电光石火

给博客添加节日雪花

二话不说先上效果图: ? 需要的朋友请看下面的说明,对JQ比较了解的朋友可以直接下载。 下载地址:jQuery圣诞下雪花.rar 注意事项 ...

2307
来自专栏Eugene's Blog

Python执行系统命令四种方法分类目录文章标签友情链接联系我们

1533
来自专栏hbbliyong

Python类、模块、包的区别

模块,在Python可理解为对应于一个文件。在创建了一个脚本文件后,定义了某些函数和变量。你在其他需要这些功能的文件中,导入这模块,就可重用这些函数和变量。一般...

1692
来自专栏决胜机器学习

《Redis设计与实现》读书笔记(十二) ——Redis键的生存时间与过期时间

《Redis设计与实现》读书笔记(十二) ——Redis键的生存时间与过期时间 (原创内容,转载请注明来源,谢谢) 1、设置方式 在redis客户端,可以通过e...

2904
来自专栏iOS Developer

Bison眼中的iOS开发多线程是这样的(二)

1393
来自专栏我的博客

YII使用命令行模式

入口文件:shell.php run(); 数据库配置文件console.php可以参考main.php 演示protected/commands/TestCo...

3623

扫码关注云+社区

领取腾讯云代金券