模块的定义

那什么是模块呢?
之前我们学过函数,我们说函数就如同包裹,它封装了一段代码,可以实现所需功能。
image.png
后来我们学了类,我们发现,类比函数更强大,它封装了属性与方法,可以实现更多的功能。
image.png
今天我们学习一下模块,这个就是江湖中争夺的储物戒指,因为它比函数、类强大很多,能够封装更多的功能代码。
用句专业术语来讲: 模块是最高级别的程序组织单元,它将程序代码和数据封装起来以便重用。也就是模块可以封装任何数据、代码。
image.png
之前我们运行的代码也是运行在一个后缀为.py的文件上,只不过我们为了方便大家,隐藏了文件名字。
image.png

每一个后缀名为.py的文件都是模块。

模块作用就是将数据、代码封装起来,以便再使用。模块不仅仅我们自己使用,也可以把它给别人使用,就像传递文件一样那么简单。
/
好了,接下来,我们看一看模块使用的方式。

方式一:使用自己的模块

建立模块,就是建立.py文件。在其中一个.py文件中引入另一个.py文件。
注意:自定议模块名字和变量名的定义很类似,都是由字母、数字、下划线组成,但是不能以数字开头,否则无法导入该模块。

如下图:我们在main.py模块中引入mytest.py模块。
image.png
请阅读main.py与mytest.py中的文件内容,并直接运行main.py文件。
image.png
image.png
直接运行main.py文件:
image.png
现在终端内出现”我是mytest模块”了。这就是main.py文件引入了mytest.py模块,将mytest.py的内容输出出来了。
就一句代码 import mytest
/
下面,我们先来看一看import

import语句

image.png
import语句可以导入一个模块,目的不仅仅是打印语句,更主要的是可以使用模块中的变量、函数与类。
image.png
我们先看一下下面代码:

#mytest.py文件
strtest = '驭风少年'

def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

class Test:
    strClass = "我是类,我是驭风少年"
    def go(self):
        print("类在运行")

print(strtest) #打印变量strtest 

hello()        #运行函数hello()

shaonian = Test()   #Test类的实例化
print(shaonian.strClass)   #打印实例属性
shaonian.go()       #调用实例方法go方法

在这段代码中,赋值变量、定义函数、定义类、使用变量、调用函数、实例化对象都在一个文件中。

我们通过使用模块,把赋值变量、定义函数、定义类放在mytest.py文件中,把使用变量、调用函数、实例化对象放在main.py文件中。
/
运行一下下面代码, 观察终端里的效果。

#main.py文件
import mytest #导入mytest模块
print(mytest.strtest) #打印mytest模块中变量strtest 

mytest.hello()        #运行mytest模块中函数hello()

shaonian = mytest.Test()   #mytest模块中Test类的实例化
print(shaonian.strClass)   #打印实例属性
shaonian.go()       #调用实例方法go方法
#mytest.py文件
strtest = '驭风少年'

def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

class Test:
    strClass = "我是类,我是驭风少年"
    def go(self):
        print("类在运行")

输出结果:
驭风少年
hello函数正在运行
我是类,我是驭风少年
类在运行

在main.py文件中,使用其他模块的代码需要注意:
image.png
import还有另外一种用法,就是import…as… 先看一下下面例子。


import mytest as ts
print(ts.strtest) #打印mytest模块中变量strtest 

ts.hello() #运行mytest模块中函数hello()

shaonian = ts.Test() #mytest模块中Test类的实例化
print(shaonian.strClass) #打印实例属性
shaonian.go() #调用实例方法go方法

如果你嫌mytest名字太长,就可以使用import…as…语句,可以将mytest的名字变成ts,这样在后面需要使用mytest模块名的地方,就可以换成ts名字使用。
/
还有,当我们需要导入多个模块时,我们可以使用逗号,将模块名隔开。

例如: import x,y,z 就是将X.py文件,Y.py文件,Z.py文件同时引入。
/
好了,这就是import语句。下面我们来学习一下from…import语句。
## from … import … 语句
![image.png](https://s2.51cto.com/images/20210911/1631340980523347.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
**from…import…语句可以将某一模块的部分代码导入到另一个模块中。**
语法如下:
![image.png](https://s2.51cto.com/images/20210911/1631341039856778.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)
还是上面那个案例,我们来改造一下。
```python
#mytest.py文件
strtest = '驭风少年'
def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

#main.py文件
from mytest import hello
from mytest import strtest
hello()
print(strtest)

输出结果:
hello函数正在运行
驭风少年

我们将mytest.py文件中的变量与函数引入main.py中使用,这样使用时无需加入”模块名”前缀。
同样,我们这次引入变量与函数,我们可以将:
from mytest import hello
from mytest import strtest
简写成:
from mytest import hello,strtest
如果想引入所有内容,还可以用来表示,
from mytest import

这就是from…import…语句的用法。

下面,学习下一个语句。
image.png
image.png
在讲
if __name__ == '__main__'语句之前,先给大家介绍一下”程序的入口”。

Python与其他语言一样,程序都要有一个运行入口。当我们运行某个py文件时,就能启动整个程序。那么这个py文件就是程序的入口。

就像上面那个案例:
image.png
当然, 以后还会遇到更复杂的情况, 只有一个主模块,引入了其他多个模块。
image.png
当我们有很多py文件在一个程序中,但是你只能指定一个程序入口。这样你就需要使用
if __name__ == '__main__'来指定某个py文件为程序入口。

第一种情况:加上这一句代码,程序和原来一样:

运行一下下面代码,观察终端里的效果。

#mytest.py文件
strtest = '驭风少年'

def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

class Test:
    strClass = "我是类,我是驭风少年"
    def go(self):
        print("类在运行")
#main.py文件
import mytest #导入mytest模块
if __name__ == '__main__':
    print(mytest.strtest)  # 打印mytest模块中变量strtest 

    mytest.hello()  # 运行mytest模块中函数hello()

    shaonian = mytest.Test()  # mytest模块中Test类的实例化
    print(shaonian.strClass)  # 打印实例属性
    shaonian.go()  # 调用实例方法go方法

执行main.py 输出结果:
驭风少年
hello函数正在运行
我是类,我是驭风少年
类在运行

这就是,当把mytest.py导入到main.py文件中,在main.py中加入
if __name__ == '__main__':执行main.py, 程序正常执行。
/
下面看另一个例子如下:

#first.py文件
import main

#main.py文件
import mytest #导入mytest模块
print("我是a模块")
if __name__ == '__main__':
print(mytest.strtest)  # 打印mytest模块中变量strtest 
mytest.hello()  # 运行mytest模块中函数hello()

shaonian = mytest.Test()  # mytest模块中Test类的实例化
print(shaonian.strClass)  # 打印实例属性
shaonian.go()  # 调用实例方法go方法
```python
#mytest.py文件
#mytest模块
strtest = '驭风少年'

def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

class Test:
    strClass = "我是类,我是驭风少年"
    def go(self):
        print("类在运行")

运行mytest.py文件,输出结果:
我是a模块

运行first.py代码,你会发现,只能输出”我是a模块”。

这是因为,此时main.py文件已经不再是程序的入口。main.py文件导入到了first.py文件中,first.py文件运行的时候,只会执行main.py文件中本身代码,不会执行
if __name__ == '__main__':后面的代码。
/
总结下if __name__ == '__main__':语句的用法
image.png
还有一种使用模块的情况,就是有些模块内的内容不希望都暴露给其他人使用,此时,我们可以指定all
指定all表示 from 只能使用指定的功能代码,而不是所有的功能代码*

此时注意,如果在引入模块时,使用的不是from mytest import *(上例中) 这种形式,而是类似import mytest这种形式时,all是不起作用的。

#mytest.py文件
#指定__all__表示  from  * 只能使用指定的功能代码,而不是所有的功能代码
__all__ = ['strtest','hello']

strtest = '驭风少年'

def hello():
    intro = "你好,我是驭风少年函数"
    print("hello函数正在运行")

class Test:
    strClass = "我是类,我是驭风少年"
    def go(self):
        print("类在运行")
#main.py文件
from mytest import *   #导入mytest模块

if __name__ == '__main__':
    print(strtest)  # 打印mytest模块中变量strtest 

    hello()  # 运行mytest模块中函数hello()

    shaonian = Test()  # mytest模块中Test类的实例化 

运行main报错:

image.png
这是因为,在mytest.py模块中,指定了all = [‘strtest’,’hello’],Test类没有指定在其中,所以使用时,会报错 Test没有定义。

好了,这就是如何使用我们自己的模块。

接下来,我们学习下如何使用他人模块。

方式二:使用他人的模块

之前我们使用过Python自带的模块
例如如下代码:

import time
print("hello")
time.sleep(3)
print("python")

运行代码你会发现,先打印“hello”,延迟3秒后才打印“python”。

这就是time模块中的time.sleep(3)语句起作用了。
我们还使用过Python自带的random模块。
例如如下代码:

import random  
num = random.randint(1,30)  # 随机从1-30之间抽取一个数字
print(num)

这就是我们使用Python自带的time与random模块的用法。
探究他人模块
Python世界中, 为我们提供了很多内置的模块; 也可以引入一些其他第三方的模块,如爬虫模块, 数据分析模块。
比如time模块,我们在Python环境中,找到了time.py文件中的代码:

#代码片段
"""Stub file for the 'time' module."""
# See https://docs.python.org/3/library/time.html

import sys
from typing import Any, NamedTuple, Tuple, Union, Optional
if sys.version_info >= (3, 3):
    from types import SimpleNamespace

_TimeTuple = Tuple[int, int, int, int, int, int, int, int, int]

if sys.version_info < (3, 3):
    accept2dyear: bool
altzone: int
daylight: int
timezone: int
tzname: Tuple[str, str]

if sys.version_info >= (3, 7) and sys.platform != 'win32':
    CLOCK_BOOTTIME: int  # Linux
    CLOCK_PROF: int  # FreeBSD, NetBSD, OpenBSD
    CLOCK_UPTIME: int  # FreeBSD, OpenBSD

if sys.version_info >= (3, 3) and sys.platform != 'win32':
    CLOCK_HIGHRES: int = ...  # Solaris only
    CLOCK_MONOTONIC: int = ...  # Unix only
    CLOCK_MONOTONIC_RAW: int = ...  # Linux 2.6.28 or later
    CLOCK_PROCESS_CPUTIME_ID: int = ...  # Unix only
    CLOCK_REALTIME: int = ...  # Unix only
    CLOCK_THREAD_CPUTIME_ID: int = ...  # Unix only

if sys.version_info >= (3, 3):
    class struct_time(
        NamedTuple(
            '_struct_time',
            [('tm_year', int), ('tm_mon', int), ('tm_mday', int),
             ('tm_hour', int), ('tm_min', int), ('tm_sec', int),
             ('tm_wday', int), ('tm_yday', int), ('tm_isdst', int),
             ('tm_zone', str), ('tm_gmtoff', int)]
        )
    ):
        def __init__(
            self,
            o: Union[
                Tuple[int, int, int, int, int, int, int, int, int],
                Tuple[int, int, int, int, int, int, int, int, int, str],
                Tuple[int, int, int, int, int, int, int, int, int, str, int]
            ],
            _arg: Any = ...,
        ) -> None: ...
        def __new__(
            cls,
            o: Union[
                Tuple[int, int, int, int, int, int, int, int, int],
                Tuple[int, int, int, int, int, int, int, int, int, str],
                Tuple[int, int, int, int, int, int, int, int, int, str, int]
            ],
            _arg: Any = ...,
        ) -> struct_time: ...
else:
    class struct_time(
        NamedTuple(
            '_struct_time',
            [('tm_year', int), ('tm_mon', int), ('tm_mday', int),
             ('tm_hour', int), ('tm_min', int), ('tm_sec', int),
             ('tm_wday', int), ('tm_yday', int), ('tm_isdst', int)]
        )
    ):
        def __init__(self, o: _TimeTuple, _arg: Any = ...) -> None: ...
        def __new__(cls, o: _TimeTuple, _arg: Any = ...) -> struct_time: ...

def asctime(t: Union[_TimeTuple, struct_time] = ...) -> str: ...
def clock() -> float: ...
def ctime(secs: Optional[float] = ...) -> str: ...
def gmtime(secs: Optional[float] = ...) -> struct_time: ...
def localtime(secs: Optional[float] = ...) -> struct_time: ...
def mktime(t: Union[_TimeTuple, struct_time]) -> float: ...
def sleep(secs: float) -> None: ...
def strftime(format: str, t: Union[_TimeTuple, struct_time] = ...) -> str: ...
def strptime(string: str, format: str = ...) -> struct_time: ...
def time() -> float: ...
if sys.platform != 'win32':
    def tzset() -> None: ...  # Unix only

if sys.version_info >= (3, 3):
    def get_clock_info(name: str) -> SimpleNamespace: ...
    def monotonic() -> float: ...
    def perf_counter() -> float: ...
    def process_time() -> float: ...
    if sys.platform != 'win32':
        def clock_getres(clk_id: int) -> float: ...  # Unix only
        def clock_gettime(clk_id: int) -> float: ...  # Unix only
        def clock_settime(clk_id: int, time: float) -> None: ...  # Unix only

if sys.version_info >= (3, 7):
    def clock_gettime_ns(clock_id: int) -> int: ...
    def clock_settime_ns(clock_id: int, time: int) -> int: ...
    def monotonic_ns() -> int: ...
    def perf_counter_ns() -> int: ...
    def process_time_ns() -> int: ...
    def time_ns() -> int: ...
    def thread_time() -> float: ...
    def thread_time_ns() -> int: ...

代码很长很长, time.py文件中的结构如下:
image.png
我们可以看到我们经常使用的sleep()函数。

#代码片段
def sleep(secs: float) -> None: ...

secs:float 就决定了,需要延迟时间,也可以传入浮点数类型的数值。

我们可以查看Python中所有内置模块的语法。

大家如果怕麻烦, 可以去Python的网站去学习;链接如下:https://docs.python.org/3/library/time.html
/
另外简单介绍一下,在jupyter notebook中是如何生成模块文件,引入模块的。
编写好模块代码后:
image.png
保留并下载:
image.png

image.png

/
/
拷贝并且重命名:
image.png
/
导入模块:
image.png