函数
模块
模块: 一个py文件就是一个模块, 每个模块之间是可以相互访问的 访问之前需要进行导入
分类: 1.系统提供的模块 math random
2.自己自定义的,自己封装的常用功能的的py文件
3.第三方模块需要进行安装。安装格式: pip install 三方模块名
导入:1. import 模块名 ;使用:模块名.内容
import random;random.randint(1, 100)
2. from 模块 import 具体某个内容
from random import randint;使用:randint(1, 100)
3. 通配符*导入 泛指该模块中所有的内容
from 模块名 import *
包
包:类比成计算机中的文件夹,一个个的文件夹就是在对计算机中的内容进行分类整理的 方便于查找东西。
计算机中的文件不允许重名,就想保存两个重名的文件,把他们放在不同的文件夹中
作用:对模块进行分类管理。给模块提供了多级命名空间。有了包之后,导入该包下面的模块。导入方式: import 一级包名.二级包名....n级包名.模块名
程序中建包:右键建立包的位置-- new -- python package;建完包之后 包中有一个__init__.py文件。
作用:向解释器解释类似于计算机中文件夹的是一个项目的包 不是一个普通文件夹。
普通的文件夹 没有再程序中为模块提供多级命名空间的作用。不同的普通文件夹中 模块不能相互访问
程序入口设定
程序入口:完成一个程序 需要几个py文件配合才能完成程序的运行。需要给一个标记 让别人知道到底是从哪个 文件开始启动执行的
在启动执行的文件中加一个if判断。判断__name__的值,如果是起始文件 __name__的值就等于 __main__;如果不是 __name__ 的值他对应的模块名
判断格式:if __name__ == "__main__":启动文件的执行内容
可变参函数
可变参数
有一种需求,在封装功能的时候并不能确定到底有多少个未知项参与功能运算 也就无法确定声明函数时形参个数。
把这个参数设置可变参数 ---> 使用一个形参接受多个实参 ---> 这个形参在函数中是容器[元组来存放的]
声明可变参数的格式
def 函数名(*变量名, 形参1,.., 形参n):
功能的运算
return 结果 # 没有结果返回 此句可省
"""
求n个数的累加和。将型参封装为可变参数
"""
def nums_sum(*num):
print(num)
'''
结果是元组容器:(12, 34, 56, 74, 86)
也可以接收实参是 元组、列表、集合等类型。
但是直接传递一个容器过来,会当作一个元素存在元组中。
若想传递成功,需要让实参和型参等价。即实参加*号
'''
total = 0
for ele in num:
total += ele
return total
if __name__ == '__main__':
res = nums_sum(12,34,56,74,86)
print(res) tuple0 = (77,45,86,34,23,23)
res = nums_sum(*tuple0) # 让实参和型参等价。即实参加*号
print(res)
关键字参数
关键字参数
调用者调用函数的时候可以传入0个或者多个带有形参名的关键字参数
声明函数时,有确定的形参个数,传递实参的 需要形参一一对应
为了避免形参多的情况下传递实参的顺序不太确定,可以传递实参的时候采用:
函数名(形参名=实参, 形参名=实参)
这种是根据形参名找到对应的形参为其赋值,不用担心顺序的问题
命名关键字参数:
调用者可以传入 形参名中没有设定 关键字参数 到底传入什么数据 需要在函数中进行判定:
例如网站注册用户时:
必填项 ---> 已知形参
选填项 ---> 可以使用命名关键字参数 接收时的格式:形参名=实参
声明方式:
接受调用者传递的位置的关键字数据时 在函数中是通过字典来接受的
def 函数名(形式参数1, 形式参数2, ... ,形式参数3, **参数名):
函数功能
def accept(name,password,**kwargs):
print(kwargs) # 结果:{'sex': '女', 'city': '北京'}
if 'city' in kwargs:
print("用户的居住地:",kwargs['city'])
if 'sex' in kwargs:
print("用户的性别:", kwargs['sex'])
if __name__ == '__main__':
accept("yaya","",sex="女",city='北京',) dict0 = {'a':97,'b':78} # 也可以穿入字典类型,加**符号
accept("pepe",'',**dict0)
匿名函数
匿名函数:生成函数一种简单方式 ---> 简单函数封装的简化。匿名函数执行一次就释放掉
使用要求:函数功能中只有一个return语句就能结束函数的这种形式可以简化成匿名函数
声明格式:lambda 形参1,形参2, .., 形参n : 功能的结果[功能的结果只能使用一句代码表示]
使用场景:对一般型参中接收函数时,可以使用匿名函数来进行传递。这样比传递一个参数是带名函数节省方法池的内存
def add(a, b):
return a + b
"""等价于"""
lambda a, b : a + b
# 对一般型参中接收函数时,可以使用匿名函数来进行传递。这样比传递一个参数是带名函数节省方法池的内存
list0 = [-19,33,54,75]
max_value = max(list0,key=lambda n:-n)
print(max_value)
# 要求是根据字典中年龄对列表进行降序排序
person_list = [{'name':'Tom','age':23},{'name':'Lili','age':45},{'name':'Susan','age':32}]
person_list.sort(key=lambda p_dict:p_dict['age'])
print(person_list)
偏函数
偏函数:偏函数是对原本存在的函数的一种修改。借助偏函数 对使用场景比较多的函数进行修改来满足场景的需求
两种方式:
自定义一个方法 间接执行原本设计的方法
使用系统提供的 funstools模块有一个方法可以转换对方法默认值的使用
# 原来使用
print('a',end='\t')
print('a',end='\t') # 自定义可变参数
def cus_print(*value):
print(*value,end='......')
# 再次使用时
cus_print('a','b')
cus_print('c','d') # 系统提供的方法
import functools
func = functools.partial(print, end="!!!!")
func('good')
闭包
闭包:在一个函数中声明另外一个函数 这种格式就叫做闭包
作用域: 只有函数有独立的作用域 在函数中声明的内容仅在函数中有效 出了函数没有任何意义 例如在函数中声明的局部变量
# 闭包
def outer():
print('外部函数')
def inner():
print('内部函数')
# 只能在外部函数中调用inner
inner()
outer()
global
使用场景:在函数中使用修改成全局变量 需要在函数内部对该变量进行全局标记 否则的话 会将该变量解释为在函数中重新声明的局部变量 与全局变量无关
nonlocal
使用场景:闭包中如果想在内层函数中 使用修改外层函数声明的局部变量 需要对该变量进行nonlocal标记 否则会被解释成 在内部函数重新声明一个变量 与外部函数的变量无关
装饰器
参考下一篇笔记 :https://www.cnblogs.com/TMMM/p/11395710.html
生成器
生成器 :
根据逻辑生成一个存放数据的容器。弥补了列表生成式的弊端。
生成器节省了内存,当生成器产生的时候 数据不会立即存放在内存中,而是取出一个存放一个
与列表生成式的区别:
列表生成式可以快速生成一批数据存放在内存中。列表生成式有一个弊端:
如果生成了大量的数据 但是只使用 前面一些的数据,此时使用列表生成式就非常的浪费内存
生成器有两种方式生成数据:
将列表生成式的中括号换成小括号(生成的数据 数据的来源 对数据的进行筛选)
类似于方法的声明 需要每次调用方法的时候需要返回生成的数据 。不是使用return 返回 [因为return直接结束函数] 使用yield代替return返回生成器中的数据
生成器中获取数据
通过next的方法 将数据从生成器中一个一个的取出
已经取出数据了 再使用next获取数据 获取的是下一个数据 不会重复的获取同一个数据
# 生成器的第一种方式生成和获取数据
ge = (num for num in range(1,1000))
print(ge) # 其类型 结果:<generator object <genexpr> at 0x106b9c480>
value = next(ge)
print(value) # 结果是:1。再次执行next(ge),结果是:2
# 获取前10个数据
for _ in range(10):
value = next(ge)
print(value)
'''
遍历的时候 需要将对应的值赋予给变量 就得起一个变量的名字来存放数据
遍历的时候 只是为了获取循环的次数,为不会获取序列中的元素 就可以使用_占位符变量
''' # 生成器的第二种方式生成和获取数据
def get_value():
for i in range(1,1000):
yield i # 此处并非结束函数,如果在yield后面还有平级的语句是会被执行的,但是是在第二次获取的时候执行
ge = get_value()
print(ge) # 其类型 结果:<generator object <genexpr> at 0x106b9c480>
value = next(ge)
print(value)
注意: 当生成其中的数据取完之后,再去取数据,就回报错
迭代器
遍历序列:for 变量 in 序列
迭代器:是相当于另外一种遍历序列的方式,通过next方法一个一个进行迭代 移动取数据的。如果一个序列想使用迭代器 前提这个序列是可以迭代的
collections模块:Iterator --- 迭代器
Iteratable --- 验证序列是否可以迭代
from collections import Iterable,Iterator # 验证指定数据是否是可迭代类型的
res = isinstance(10,Iterable)
print(res) # 结果 :False。 整型是不可以迭代的 res = isinstance('',Iterable)
print(res) # 结果 :True。字符串类型是可以迭代的 res = isinstance((''),Iterable)
print(res) # 结果 :True。元组类型是可以迭代的 res = isinstance([''],Iterable)
print(res) # 结果 :True。列表类型是可以迭代的 res = isinstance({''},Iterable)
print(res) # 结果 :True。集合类型是可以迭代的 res = isinstance({'':10},Iterable)
print(res) # 结果 :True。字典类型是可以迭代的
"""
Iterable 这个类型验证的结果是:所有的序列都是可以迭代的[遍历],for in 进行遍历
能用for in进行遍历的序列,不一定能用迭代器进行遍历。迭代器遍历使用next方法一个一个迭代的
生成器 --- 可以使用next来迭代 --- 就可以使用迭代器迭代。
列表 --- 可以使用for in进行遍历 --- 但不能使用迭代器迭代
""" # 若想使用迭代器进行迭代列表类型,需要使用iter(序列)进行转换,
# 转化成Iterator迭代器的类型才可以使用next方法进行遍历迭代
list0 = [12,34,64,76,34,5,86]
it = iter(list0)
value = next(it)
print(value) # 结果:12
value = next(it)
print(value) # 结果:34