Ta会如7而至吗

一、模块与导入模块


1.什么是模块?

①在Python中,一个.py文件就称之为一个模块(Module)。模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。模块也有一点封装的味道,比如数据的封装是容器(列表,元组,字典等),语句的封装是函数,方法和属性的封装是类,那么子程序的封装就是模块。

在这里插入图片描述
②模块分为三种:

1)内置标准模块(又称python标准库)执行help(‘modules’)查看所有python自带模块列表
2)第三方开源模块,可通过pip install 模块名联网安装,比如numpy
3)自定义模块

2.模块的特点

python自带的IDLE(shell)是一种交互式编程,如果你从 Python 这个解释器退出再进入,那么你定义的所有的方法和变量就都消失了。而模块的作用就是提供一种保存程序(方法和变量)的方法,以便下次使用。更多的模块还有许多特点,比如:

①提高编程效率(模块导入!)
②模块能够使你的Python代码段有逻辑(可读性提高)
③避免函数名和变量名冲突(命名空间稳住!)

3.导入模块的几种方法

1.导入整个模块

方法: import 模块名
要让函数是可导入的,首先得先创建模块,模块的扩展名为.py的文件,包含要导入到程序中的代码。下面来穿件一个只包含一个函数 uuu.py()的模块,然后在同目录下另一个创建一个名为ppp.py()的文件,在其中导入uuu.py()模块。

# uuu.py
def car(car_name):
    print('I have a %s car!' % car_name)
# ppp.py
import uuu  # 导入uuu模块
uuu.car('Toyota')  # 在此用‘模块名.函数名‘调用带入模块的函数
# I have a Toyota car!

uuu.car('Mazda')  # 再调用一次
# I have a Mazda car!

python在读取这个文件时,代码行 import uuu 让py打开car.py,并将其中的所有函数复制到这个程序中,我们看不到这些复制的代码,也不需要知道这些代码是什么样的,我们只需知道在ppp.py()中,我们可以使用uuu.py()中定义的所有函数

②导入特定的函数

方法:from 模块名 import 函数名
还可以导入模块中特定的函数,比如uuu.py()中含有两个或以上的函数,而我在ppp.py()中仅需要用到其中一个名为car()的函数,那么就可以使用这种导入方法

# uuu.py
def car(car_name):
    print('I have a %s car!' % car_name)


def dog(dog_name):
    print('I have a %s dog!' % dog_name)


def pen(pen_name):
    print('I have a %s pen!' % pen_name)
from uuu import car  # 导入uuu模块中的car函数
car('Toyota')   # 此处调用直接使用函数名
# I have a Toyota car!

这里若想导入模块中多个特定函数,可使用逗号分隔函数名

# ppp.py
from uuu import car, dog  # 导入模块中两个特定函数
car('Toyota')  # I have a Toyota car!
dog('hanhan')  # I have a hanhan dog!

使用这种语法时,调用函数无需使用句点法,只需要指定其名称。

第三种:使用as给函数指定别名

方法:from 模块名 import 函数名 as 函数别名
如果导入的函数的名称太长,或者可能与程序中现有的程序名称冲突,可指定简短而独一无二的别名———函数的另一个名称,类似于外号

# ppp.py
from uuu import car as c  # 导入uuu模块中的car函数

c('GTR')  # I have a GTR car!

第四种:使用as给模块指定别名

方法:import 模块名 as 模块别名
通过给模块指定简短的别名,可以更轻松地调用模块中的函数,我们在读别人的程序时应该也见过 import numpy as np 这就是指定给导入的模块别名

# ppp.py
import numpy as np
import uuu as u

u.car('Nissan')  # I have a Nissan car!
print(np.random.randint(0, 10))  # 5

第五种: 导入模块中的所有函数

方法:from 模块名 import *
使用(*)号运算符可让python导入模块中的所有函数(事实上是__all__中的所有函数)

# ppp.py
from uuu import *
car('BMW')  # I have a BMW car!
dog('hanhan')  # I have a hanhan dog!
pen('red')  # I have a red pen

由于导入了每个函数,可通过名称来调用每个函数,无需句点法。然鹅这样的做法貌似不太被推荐,因为,如果模块中函数的名称与你的项目中使用的名称相同,python遇到多个相同的名称或变量时,就有可能覆盖了函数,而不是分别导入函数,进而带来一些都是意想不到的结果

tips:稳妥的做法是,要么只导入你使用的函数,要么导入整个模块并使用句点表示法,这样可以让代码更清晰,更易于阅读与理解

二、命名空间与if __name__ == '__main__'


1.python的命名空间

Python使用叫做命名空间的东西来记录变量的轨迹。命名空间是一个 字典(dictionary) ,它的键就是变量名,它的值就是那些变量的值。在一个 Python 程序中的任何一个地方,都存在几个可用的命名空间。

①每个函数都有着自已的命名空间,叫做局部命名空间(Function & Class:Local Namespaces),它记录了函数的变量,包括函数的参数和局部定义的变量。

②每个模块拥有它自已的命名空间,叫做全局命名空间(Module:Global Namespaces),它记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。

③还有就是内置命名空间(Built-in Namespaces),任何模块均可访问它,它存放着内置的函数和异常。

2.命名空间查找顺序

二、命名空间查找顺序

当一行代码要使用变量 x 的值时,Python 会到所有可用的名字空间去查找变量,按照如下顺序:
①局部命名空间:特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数 x,Python 将使用它,然后停止搜索。
②全局命名空间:特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
③内置命名空间:对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。
即按照 Local Namespaces --> Global Namesspaces --> Built-in Namesspaces 顺序查找,如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,NameError: name ‘uuu’ is not defined。

tips:如果含有内嵌函数时:
①先在当前 (嵌套的或 lambda) 函数的命名空间中搜索
②然后是在父函数的命名空间中搜索
③接着是模块命名空间中搜索
④最后在内置命名空间中搜索

举一个简单的例子看一下命名空间如解决的函数名冲突的方法,因为模块都拥有自己的命名空间,所以会分别在自己的命名空间查找函数,即使名字相同也不会出错

# ppp.py
import uuu
import ccc
uuu.car('BMW')  # I have many Mazda car!
ccc.car('Mazda')  # I have many Mazda car!

3.if __name__ == '__main__'

python文件有两种运行方式:

①以模块的形式进行

②以脚本的形式进行

直接上例子,我们创建了一个名为 uuu.py 的文件,里面的是变量 PI 的值,其中的main函数是用于测码

# uuu.py
PI = 3.14
def main():
    print("PI:", PI)

main()

# PI: 3.14

刚我们在另一个名为ppp.py 的文件中导入该模块中的 PI 时,并用来计算面积

# ppp.py
from const import PI

def calc_round_area(radius):
    return PI * (radius ** 2)

def main():
    print("round area: ", calc_round_area(2))


main()

'''
PI: 3.14
round area:  12.56
'''

我们看到 uuu.py 中的 main 函数也被运行了,实际上我们不希望它被运行,因为 uuu.py 提供的 main 函数只是为了测试常量定义(测试代码)。这时if __name__ == '__main__'派上了用场,我们把 uuu.py 改一下,添加if __name__ == "__main__"

PI = 3.14

def main():
    print("PI:", PI)

if __name__ == "__main__":
    main()

运行 uuu.py,输出如下:

PI: 3.14  # 没有变化

运行 area.py,输出如下:

round area:  12.56  

__name__:是内置变量,可用于表示当前模块的名字。由此我们可知:如果一个 .py 文件(模块)被直接运行时,其__name__值为__main__,即模块名为__main__。所以,添加了if __name__ == '__main__'后,你既可以把这个文件当做脚本来运行也可以当做调用模块来运行,其意思是:当 .py 文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行,此文件作为脚本来执行 ;当 .py 文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行,此文件作为导入模块来执行。

更深入的理解请参考:Python 中 name == ‘main’ 的作用

三、搜索路径与包


1.何谓搜索路径?

python中的导入模块与搜索路径密切相关,当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。

import sys
for s in sys.path:
    print(s)
'''
C:\Users\Administrator\Desktop\魔鬼般的Python\11111
C:\Users\Administrator\Desktop\魔鬼般的Python\11111
E:\百度网盘Download\python-3.8.2\python38.zip
E:\百度网盘Download\python-3.8.2\DLLs
E:\百度网盘Download\python-3.8.2\lib
E:\百度网盘Download\python-3.8.2
E:\百度网盘Download\python-3.8.2\lib\site-packages
'''

搜索路径是由一系列目录名组成的,Python 解释器就依次从这些目录中去寻找所引入的模块。这看起来很像环境变量,事实上,也可以通过定义环境变量的方式来确定搜索路径。搜索路径是在 Python 编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在 sys 模块中的 path 变量中。

2.如何添加搜索路径?

前面我们提到在相同目录下导入模块,这是因为sys.path的目录可以帮助我们去自动寻找到这个要被导入的模块,而事实上,我们也是可以从不同的目录中导入模块,使用sys.path.append()可以"为所欲为"的导入任意模块

xiezi.py 显然不在于ppp.py在一个目录下
在这里插入图片描述
直接导入,失败

# ppp.py
import xiezi

xiezi.converse()  # ModuleNotFoundError: No module named 'xiezi'

下面在添加路径后,成功导入xiezi.py模块

# ppp.py
import sys
sys.path.append(r'C:\Users\Administrator\Desktop\魔鬼般的Python')
import xiezi

xiezi.converse()  # hi, i am cw

3.python中的包

1.什么是包?

包是一种通过".模块名"(点模块名称)来组织python模块名称空间的方式,我们穿件的每个文件夹都可以被称为包。但是要注意,在python2中规定. 包内必须存在__init__.py文件。创建包的目的不是为了运行, 而是被导入使用. 包只是一种形式而已,包的本质就是一种模块。

2.如何创建包?

创建包分为三个步骤:

  • 创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字。
  • 在文件夹中创建一个 __init__.py 的模块文件,内容可以为空。(必须要有,才会被当做包!)
  • 将相关的模块放入文件夹中。

3.例子

不妨假设你想设计一套统一处理声音文件和数据的模块(或者称之为一个"包")。

现存很多种不同的音频文件格式(基本上都是通过后缀名区分的,例如: .wav,.aiff,.au),所以你需要有一组不断增加的模块,用来在不同的格式之间转换。

并且针对这些音频数据,还有很多不同的操作(比如混音,添加回声,增加均衡器功能,创建人造立体声效果),所以你还需要一组怎么也写不完的模块来处理这些操作。

这里给出了一种可能的包结构(在分层的文件系统中):

sound/                          顶层包
      __init__.py               初始化 sound 包
      formats/                  文件格式转换子包
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  声音效果子包
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  filters 子包
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

在导入一个包的时候,Python 会根据 sys.path 中的目录(同文件夹)来寻找这个包中包含的子目录。

目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包,最简单的情况,放一个空的 __init__.py 就可以了。

import sound.effects.echo

这将会导入子模块 sound.effects.echo。 他必须使用全名去访问:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

还有一种导入子模块的方法是:

from sound.effects import echo

这同样会导入子模块: echo,并且他不需要那些冗长的前缀,所以他可以这样使用:

echo.echofilter(input, output, delay=0.7, atten=4)

还有一种变化就是直接导入一个函数或者变量:

from sound.effects.echo import echofilter

同样的,这种方法会导入子模块: echo,并且可以直接使用他的 echofilter() 函数:

echofilter(input, output, delay=0.7, atten=4)

注意当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。

设想一下,如果我们使用 from sound.effects import * 会发生什么?

Python 会进入文件系统,找到这个包里面所有的子模块,一个一个的把它们都导入进来。

导入语句遵循如下规则:如果包定义文件 __init__.py 存在一个叫做 __all__ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。

这里有一个例子,在 sounds/effects/__init__.py中包含如下代码:

__all__ = ["echo", "surround", "reverse"]

这表示当你使用 from sound.effects import *这种用法时,你只会导入包里面这三个子模块。

如果 __all__ 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包 sound.effects 和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。

这会把 __init__.py 里面定义的所有名字导入进来。并且他不会破坏掉我们在这句话之前导入的所有明确指定的模块。

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

这个例子中,在执行 from...import 前,包 sound.effects 中的 echosurround 模块都被导入到当前的命名空间中了。

通常我们并不主张使用 * 这种方法来导入模块,因为这种方法经常会导致代码的可读性降低。

部分习题与解答

1.怎么查出通过 from xx import xx导入的可以直接调用的方法?

答:正如前面所说的 from package import item 这种形式,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。我们作为导入者,是应该对自己导入的 item 有所理解的,那就请各位 item 大佬们分别入座吧

① 若是子模块,直接help(模块名)查看里面的函数有哪些

from mypackage import uuu

help(uuu)
'''
FUNCTIONS
    car(car_name)
        # uuu.py
    
    dog(dog_name)
    
    pen(pen_name)
'''

②若是函数,那就很好办了,你导入了什么函数,那什么函数就是可以直接调用的嘛

③若是类,那就使用__dict__将类的信息打印出来

from uuu import A
print(A.__dict__)
'''
'__init__': <function A.__init__ at 0x0000000002475700>, 
'setab': <function A.setab at 0x0000000002475790>,
 'printab': <function A.printab at 0x0000000002475820>
'''

不管是导入自己编写的模块还是别人的模块,总归一句话,用help函数能解决大部分遇到的问题

2、了解Collection模块,编写程序以查询给定列表中最常见的元素。

题目说明:

输入:language = [‘PHP’, ‘PHP’, ‘Python’, ‘PHP’, ‘Python’, ‘JS’, ‘Python’, ‘Python’,‘PHP’, ‘Python’]

输出:Python

from collections import Counter


def most_element(language):
    print((max(list(Counter(language).items()), key=lambda a: a[1]))[0])


language1 = ['PHP', 'PHP', 'Python', 'PHP', 'Python', 'JS', 'Python', 'Python', 'PHP', 'Python']

most_element(language1)  # Python
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值