进阶学Python:Python的高阶函数和模块 | 八月更文挑战

687 阅读8分钟

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

📖前言

三毛曾经感慨:

“心之何如,有似万丈迷津,横亘千里,其中并无舟子可以渡人,除了自渡,他人爱莫能助。” ——生命的洪流中,终其一生,我们都在学会怎么做自己的摆渡人。

关于安装和汉化可以观看博主的这篇文章《VsCode下载安装及汉化 》以及Python系列:windows10配置Python3.0开发环境!,安装完毕重启VsCode!


Come on!什么是高阶函数?

高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

参数为函数

'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-15 13:42:21
'''

#参数为函数
def chen():
    print("in the chen..")
def jia(func):
    func()
    print("in the jia..")

jia(chen)

返回值为函数

'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-15 13:42:21
'''

#返回值为函数
def chen():
    print("in the chen..")
def jia(func):
    print("in the jia..")
    return bar
res=jia(chen)
res()

以上两个示例中,函数jia()为高阶函数,示例一中函数bar作为jia的参数传入,示例二中函数bar作为jia的返回值。

  注:函数名(例如chen 、jia)-->其为该函数的内存地址;函数名+括号(例如 chen()、jia() )-->调用该函数。


高阶函数-map、filter、reduce

这三个函数均为高阶函数,其也为Python内置的函数。接下来我们看一下这三个函数的用法以及其内部原理是怎样的:

map函数

map函数接收的是两个参数,一个函数,一个序列,其功能是将序列中的值处理再依次返回至列表内。

map函数的机制:

'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-16 16:08:25
'''

num=[1,2,3,4,5]
def square(x):
    return x**2
#map函数模拟
def map_test(func,iter):
    num_1=[]
    for i in iter:
        ret=func(i)
        # print(ret)
        num_1.append(ret)
    return num_1.__iter__() #将列表转为迭代器对象

#map_test函数
print(list(map_test(square,num)))
#map函数
print(list(map(square,num)))

#当然map函数的参数1也可以是匿名函数、参数2也可以是字符串
print(list(map_test(lambda x:x.upper(),"Sunny Chen")))
print(list(map(lambda x:x.upper(),"Sunny Chen")))

# 输出为:
# [1, 4, 9, 16, 25]
# [1, 4, 9, 16, 25]
# ['S', 'U', 'N', 'N', 'Y', ' ', 'C', 'H', 'E', 'N']
# ['S', 'U', 'N', 'N', 'Y', ' ', 'C', 'H', 'E', 'N']
filter函数

filter函数也是接收一个函数和一个序列的高阶函数,其主要功能是过滤。其返回值也是迭代器对象:

filter函数的用法以及其机制:

'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-16 16:12:42
'''

names=["Chen","Sunny","xiaojai"]
#filter函数机制
def filter_test(func,iter):
    names_1=[]
    for i in iter:
        if func(i): #传入的func函数其结果必须为bool值,才有意义
            names_1.append(i)
    return names_1
#filter_test函数
print(filter_test(lambda x:x.islower(),names))
#filter函数
print(list(filter(lambda x:x.islower(),names)))

# 输出为:
# ['xiaojai']
# ['xiaojai']
reduce函数

reduce函数也是一个参数为函数,一个为可迭代对象的高阶函数,其返回值为一个值而不是迭代器对象,故其常用与叠加、叠乘等,图示例如下:

'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-15 13:42:21
'''

#reduce函数不是内置函数,而是在模块functools中的函数,故需要导入
from functools import reduce

nums=[1,2,3,4,5,6]
#reduce函数的机制
def reduce_test(func,array,ini=None): #ini作为基数
    if ini == None:
        ret =array.pop(0)
    else:
        ret=ini
    for i in array:
        ret=func(ret,i)
    return ret
#reduce_test函数,叠乘
print(reduce_test(lambda x,y:x*y,nums,100))
#reduce函数,叠乘
print(reduce(lambda x,y:x*y,nums,100))

# 输出为:
# 72000
# 72000

Come on!模块(module)的介绍

模块的定义:

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,将会显得越来越杂乱无章,故使得代码的维护性越来越差。例如:在分析中国的每个城市的人口数量变化情况时,若我们把对每个城市的人口数量分析放在一个word文档内,那要查找某一个城市的人口数量变化情况,那岂不是很难?故我们可以把对一个城市的分析写在一个文件内,这样想要找某个城市的数据分析则会容易得多。
这时候我们会根据不同的功能将不同用途的代码放置在不同的.py文件内,这样做的好处就是:

  • 一、大大的提高了代码的可维护性。
  • 二、开源。编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
  • 三、使用模块可以避免变量名和函数名冲突。

而一个 .py文件就是一个模块。

模块的分类:

模块的通常而言有以下三种:

  1. Python标准库,例如:time、random、json等模块

  2. 第三方模块 ->例如:Pandas(python实现的类似R语言的数据统计、分析平台。

  3. 自定义模块。即自写的.py文件


模块的导入

一、import语句

  • import module1[, module2[,... moduleN],直接导入模块,这种方式可以用于导入本目录下的模块,以及内置模块
  • 当我们使用import语句的时候,Python解释器是怎样的找到对应的文件的呢?
  • 其实解释器有其搜索路径,可通过导入sys模块,调用sys.path来查看。当使用import 导入模块时,则按照该搜索路径进行查找,故若该被导入模块文件在这些搜索路径中,则直接可以使用import方法导入。例如:
  • ['/usr/lib/python3.6/python_learning/my_module','/usr/lib/python3.6','/usr/lib/python3.6/plat-x86_64-linux-gnu','/usr/lib/python3.6/lib-dynload','/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages'],若该模块处于这些路径,则可以直接使用import方法。

二、from...import语句

  • from module_name import name1[, name2[, ... nameN]],导入模块中的函数或者变量等。
  • 这种导入方式不会将整个module_name模块导入到当前的命名空间中来。仅导入指定的函数(函数即变量)或者变量等。
  • *而from module_name import则是导入模块 module_name下的所有函数或者变量等。
  • 注:这种方法不推荐使用,由于导入的函数或者变量不明确则可能会与本文件中的函数名或者变量名冲突。

包(package)

还是上面那个例子,若对每个城市的人口数量进行数据分析,即使将一个城市的人口数量分析放在一个Word文档中,由于中国的城市这么多,那么我们可以根据省进行划分,则可根据省创建文件夹,将该省内的城市的数据分析放入该文件夹内。包(package)也是同样的道理,只不过包(package)是带有__init__.py文件的文件夹(Directory)。

包(package)的好处:

  • ①、在不同的包内模块名即便相同也不受影响。在很多情况下,我们通常会在不同的包内创建相同的文件名。
  • ②、可根据模块的功能不同将文件进行分类,故包的存在可以使文件的分类更加清晰、使得代码的定位更加明确。

注:每次调用某个包的时候,即执行该包下__init__.py文件。 在这里插入图片描述

例如,图中的my_module、module_test即为包(package),而其中必然会有一个__init__.py文件。

包(package)中文件的导入(需重点掌握前两种。)

在这里插入图片描述


if __name__ ="__main__" 的用法

如果我们是直接执行某个 .py文件 的时候,该文件中那么 ”__name__ == '__main__' “是 True,但是我们如果从另外一个 .py文件 通过import导入该文件的时候,这时__name__的值就是我们这个py文件的名字而不是__main__。

if __name__ = "__main__" 的功能:

  • 可以在被导入模块中用于调试(在被导入模块中 if __name__ ="__main__" :-->True),而在导入该模块的文件中是不会被执行的(在导入模块的文件中,导入该模块时执行 if __name__ = "__main__" :-->Flase)
  • 用于接口文件(bin)中使用 if __name__ ="__main__":mian.run() ,告诉别人我的模块你可以调用但是不能够修改。
'''
@Descripttion: 这是一个文件头注释!
@version: 1.0.0
@Company: DCIT-SH
@Author: Sunny Chen
@Date: 2019-10-15 13:42:21
@LastEditors: Sunny Chen
@LastEditTime: 2019-10-16 16:34:48
'''

#-----》在web1.web2.web3包下的cal.py文件中
def add(x,y): #加法
    return x+y
def multi(x,y): #乘法
    return x*y
#调试cal.py文件中的函数
if __name__ = "__mian__":
    m = add(3,2)
    print(m) 
#输出为:__main__

#-----》在导入模块的文件 web_test.py文件中
from web1.web2.web3 import cal
print( __name__)
#输出为:web1.web2.web3.cal

#同时在web_test.py中不会执行cal.py中的 if __name__:"__main__" 下的内容。

快去动手试试吧!

🎉最后

  • 更多参考精彩博文请看这里:陈永佳的博客

  • 喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!