模块细节

今日内容概要

  • 匿名函数
  • 面对过程编程
  • 模块介绍
  • 模块的搜素路径
  • 模块的两种路径

今日内容详解

1.匿名函数

'''什么是匿名函数
	匿名函数就是没有名字的函数
   为什么要使用匿名函数
   	用于临时使用一次的场景
   如何定义匿名函数
'''
def func(x,y):
    return x + y
# 将上面的写成匿名函数
# 关键字 lambda 
res = (lambda x, y: x + y)(1,2)  # lambda 不需要return,本身自带return
print(res)
>>> 3 
# 但一般很少这样使用,匿名函数结合其他的内置函数使用,因为匿名函数就是临时使用,没必要特意去造这个函数,还需要去想名字

### 匿名函数使用场景
# max() 函数 获取最大值
# max(),里面可以加入一个key的索引

salaries = {
    "axx":45000
    "bxx":5000
    "cxx":37000
}

# 如果我们直接比较的话,max可以取出key而不是value的值
# 这时我们需要引进匿名函数



print(max(salaries))  # 只能获取key
def f(name):
    return salaries[name]
print(max(salaries,key=f))


# 针对上面临时使用的函数就可以使用lambda 

print(max(salaries,key=lambda name :salaries[name]))   # lambda将函数简化


# min 获取最小值
# 同理
print(min(salaries,key=lambda name:salaries[name]))


# map 函数

# map() 会根据提供的函数对指定序列做映射。
# 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

# 语法

# map(function,iterable,...)

# function -- 函数
# iterable --一个或者多个序列  
# 在python3中为迭代器

names = ['wuxie','kkk','cccc']
res = map(lambda name: name+'_vip',names)
print(list(res))

>>> ['wuxie_vip', 'kkk_vip', 'cccc_vip']


# filter(function, iterable) 函数

# filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。

# 该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。


# 简单使用,结合lambda
names = ['wuxie','wi_vip','wxx_vip']
res = filter(lambda name:name.endswith('_vip'),names)
print(list(res))

>>> ['wi_vip', 'wxx_vip']

# reduce()函数

# reduce() 函数会对参数序列中元素进行累积。

# 函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

# 注意:Python3.x reduce() 已经被移到 functools 模块里,如果我们要使用,需要引入 functools 模块来调用 reduce() 函数: 
 # from functools import reduce

# reduce() 函数语法
# reduce(function, iterable[, initializer])
# function -- 函数,有两个参数
# iterable -- 可迭代对象
# initializer -- 可选,初始参数

from functools import reduce
res = reduce(lambda x, y:x + y,[1,2,3,4],2)
print(res)

>>>  12

2.面对过程编程思想

'''
面对过程编程思想
	过程就是流程,是一种以事件为中心的编程思想。就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
	基于该思想写程序就好比在设计一条条的流水线
'''
'''
	优点:复杂的问题流程化,进而简单化
	缺点: 牵一发而动全身,扩展性差
'''

3.模块

模块介绍

1.含义: 把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法。

模块使用

模块的来源:
    1.自带的:
        内置
        标准库
    2.第三方的
    3.自定义模块

 import 语句 
 # 例如
  spam.py  #  文件名

print('from the spam.py')
money = 1000

def read1():
    print('spam模块:',money)
    
def read2():
    print('spam模块')
    read1()
    
def change():
    global money
    money = 0
    
    
import spam

print(spam.money)

>>>
from the spam.py
1000


# 首次导入模块会发生三件事

# 1.执行源文件代码
# 2.产生一个新的名称空间用于存放源文件执行过程中产生的名字
# 3.在当前执行文件所在的名称空间中得到一个名字spam,改名字指向新创建的模块名称空间,若想引用模块名称空间中的名字,需要加上该前缀

'''
加上spam.作为前缀就相当于指名道姓地说明要引用spam名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突,并且若当前执行文件的名称空间中存在x,执行spam.read1()或spam.change()操作的都是源文件中的全局变量x。
'''
# 导入的模块中可能包含有python内置的模块、第三方的模块、自定义的模块,为了便于明显地区分它们,我们通常在文件的开头导入模块,并且分类导入,一类模块的导入与另外一类的导入用空行隔开
# 导入函数的细节
# 1.python内置模块
# 2.第三方模块
# 3.程序员自定义模块
# 我们也可以在函数内导入模块,对比在文件开头导入模块属于全局作用域,在函数内导入的模块则属于局部的作用域。
import ljkf as f  # 将模块名别名,一般面对特别长的模块名

from - import 语句

# 语法与import 基本一致,使用时不需要加上模块名,直接调用即可
# 优点:可以使代码更加简洁
# 缺点:容易与当前名称空间中的名字冲突,如果当前名称空间存在相同的名字,则后定义的名字会覆盖之前定义的名字


from spam import money ,read1,read2,change

money = 200
print(money)
print(read1)
print(read2)
print(change)

>>>
from the spam.py
200
<function read1 at 0x000002182F8E95E0>
<function read2 at 0x000002182F8E9430>
<function change at 0x000002182F8E93A0>

# 上面代码可以简化 *
from spam import *   #  * 是将所有导入

# 如果我们需要引用模块中的名字过多的话,可以采用上述的导入形式来达到节省代码量的效果,但是需要强调的一点是:只能在模块最顶层使用的方式导入,在函数内则非法,并且的方式会带来一种副作用,即我们无法搞清楚究竟从源文件中导入了哪些名字到当前位置,这极有可能与当前位置的名字产生冲突。模块的编写者可以在自己的文件中定义__all__变量用来控制*代表的意思

__all__ = ['money','read1']  # 该列表中所有的元素必须是字符串类型,每个元素对应spam.py中的一个名字

循环导入

'''导入模块时,仅在第一次会产生名称空间


循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败、抛出异常,究其根源就是在python中,同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未完全加载完毕也不会去重复执行内部代码
'''

 # 如何解决
 
# 方案一:
# 导入语句放到最后,保证在导入时,所有名字都已经加载过
print('正在导入m1')

x = 'm1'

from m2 import y



# 方案二:
# 导入语句放到函数内,只有在调用函数时才会执行其内部代码
print('正在导入m1')

def f1():
    from m2 import y
    print(x, y)
    
x = 'm1'

### 注意:循环导入问题大多数情况是因为程序设计失误导致,上述解决方案也只是在烂设计之上的无奈之举,在我们的程序中应该尽量避免出现循环/嵌套导入,如果多个模块确实都需要共享某些数据,可以将共享的数据集中存放到某一个地方,然后进行导入

搜素模块的路径与优先级

 # 模块搜素路径,优先级从高到低
 # 1.内存
 # 2.内置
 # 3.sys.path

#### sys.path 输出是一个列表,其中第一项是空串'',代表当前目录(若是从一个脚本中打印出来的话,可以更清楚地看出是哪个目录),亦即我们执行python解释器的目录(对于脚本的话就是运行的脚本所在的目录)。

### 因此若像我一样在当前目录下存在与要引入模块同名的文件,就会把要引入的模块屏蔽掉。

### 了解了搜索路径的概念,就可以在脚本中修改sys.path来引入一些不在搜索路径中的模块。

区分py文件的两种用途

一个Python文件有两种用途,一种被当主程序/脚本执行,另一种被当模块导入,为了区别同一个文件的不同用途,每个py文件都内置了__name__变量,该变量在py文件被当做脚本执行时赋值为“__main__”,在py文件被当做模块导入时赋值为模块名

# 文件名func.py
if __name__ == '__main__':
    print("程序自身在运行")
else:
    print("我来自另一模板")
    
    
 # 当自身在py文件中运行
>>> 程序自身在运行

# 当被模块导入时
import func

>>> 我来自另一模板
posted on   zhifwu  阅读(31)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示