一、偏函数【了解】
默认参数:可以降低函数调用的难度
偏函数:对函数参数做一些控制的函数
注意:偏函数不需要自定义,直接使用【系统函数】
代码演示:
# int() 默认将其他数据类型转换为整型(10进制)
print(int("123")) # 123
# int() 函数还提供了第二个参数 base控制转换为几进制
print(int("123",base = 8)) # 83 (8进制数)
print(int("110",base = 2)) # 6
import functools # 引入functools模块
# 系统提供了 functools.partial 可以创建一个偏函数
int2 = functools.partial(int,base = 8)
print(int2("123")) # 83
'''
偏函数主要用于内置函数,当内置函数不能满足我们的一些需求的时候,我们可以在这个内置函数的基础上生成一个新的函数(偏函数),两个函数可以实现不同的需求.
'''
二、闭包【掌握】
如果在一个函数的内部定义另外一个函数,外部的函数叫做外函数,内部的函数叫做内函数
如果在一个外部函数中定义一个内部函数,并且外部函数的返回值是内部函数,就构成了一个闭包,则这个内部函数就被称为闭包【closure】
实现函数闭包的条件:
1.必须是函数嵌套函数
2.内部函数必须引用一个定义在闭合范围内的外部函数的变量,----内部函数引用外部变量
3.外部函数必须返回内部的函数
代码演示:
# 闭包: 如果在一个外部函数中定义一个内部函数,并且外部函数的返回值是内部函数,就构成了一个闭包,则这个内部函数就被称为闭包【closure】
# 最简单的闭包
# 外部函数
def outer():
# 内部函数
def inner():
print("lala")
return inner # 将内部函数返回
fn = outer() # fn =====> inner函数
fn() # 相当于调用了inner函数 输出 lala
# 内部函数使用外部函数的变量
def outer1(b):
a = 10
def inner1():
# 内部函数可以使用外部函数的变量
print(a + b)
return inner1
fun1 = outer1(12)
fun1()
'''
注意:
1.当闭包执行完毕后,仍然能够保存住当前的运行环境
2.闭包可以根据外部作用域的局部变量得到不同的效果,类似于配置功能,类似于我们可以通过修改外部变量,闭包根据变量的改变实现不同的功能.
应用场景: 装饰器
'''
三、变量的作用域
1.出现的原因
变量的作用域:变量可以被使用【被访问】的范围
程序中的变量并不是在任意的语句中都可以被访问,访问权限取决于这个变量被定义在哪个位置
在python中 分支语句 if..else if.. 和 循环for 等 是不存在变量作用域问题的.
if 5 > 4:
a = 11
print(a)
for i in range(10):
b = 32
print(b)
# 在 分支结构中if.. if..esle 和 循环中for in 不存在作用域的问题.在他们的外面可以直接访问里面定义的变量.
def fn():
c = 99
# print(c) # name 'c' is not defined
2.作用范围划分
局部作用域:L【Local】
函数作用域:E【Enclosing】 将变量定义在闭包外的函数中
全局作用域:G【Global】
內建作用域:B【Built-in】
代码演示:
def fn():
c = 99
# print(c) # name 'c' is not defined
1.函数内部定义的变量在函数外部不能访问.
# 全局作用域:
num1 = 12 # 全局作用域,在函数内部和外部可以直接访问
def test():
num2 = 87 # 函数作用域
print(num1)
# print(num3) # name 'num3' is not defined
def inner():
num3 = 55 # 局部作用域
# 在内部函数中,可以访问全局作用域\函数作用域\局部作用域的变量
print(num1,num2,num3)
return inner
test()
print(num1)
# print(num2)
fn = test()
fn()
n = int("28") # builins 内置函数在调用的时候的作用域,这是python解释器自己定义的.
总结:
1. 在 分支结构中if.. if..esle 和 循环中for in 不存在作用域的问题.在他们的外面可以直接访问里面定义的变量.
2.作用域主要体现在函数中, 函数内部定义的变量在函数外部不能访问.
3.函数内部可以访问函数外部的变量.
3.全局变量和局部变量【掌握】
全局变量:将变量定义在函数的外面
局部变量:将变量定义在函数的内部
注意:局部变量只能在其被声明的当前函数中使用,而全局变量可以在整个程序中使用
5.global和nonlocal关键字的使用【掌握】
使用场景:当内部作用域【局部作用域,函数作用域】想要修改全局变量的作用域的时候
1.global
代码演示:
num = 11
def test():
num = 78
print(num)
test() # 78
print(num) # 11
# 若想在函数的内部,对全局变量进行修改,需要使用global关键字
num1 = 11
def test1():
# 通过global关键字将函数内部声明变量变为了全局变量
global num1
num1 = 75
print(num1)
test1() # 75
print(num1) # 75
2.nonlocal
代码演示:
# nolocal 关键字主要用于闭包函数中
# nolocal关键字用于闭包函数中
x = 15 # 全局变量
def outer():
x = 19
def inner():
# x = 23
# global x # 使用的是 x = 15
nonlocal x # 这时候使用的变量是 x = 19
x += 1
print("inner:",x)
return inner
# 闭包会保存住当前的运行环境
test = outer()
test() # 20
test() # 21
test() # 22
num = 11
def demo():
print(num)
demo() # 11
demo() # 11
demo() # 11
四、列表生成式和生成器【掌握】
1.列表生成式/列表推导式
list comprehension
系统内置的用于创建list的方式
range(start,end,step)缺点:生成的列表一般情况下都是等差数列
代码演示:
# 最基本的列表
# 1.生成1-10之间所有的数字
list1 = list(range(1,11))
print(list1)
# 需求:通过程序的方式生成列表 [1,4,9,16,25]
#第一种方法:使用原始的方式生成
list2 = []
for i in range(1,6):
list2.append(i ** 2)
print(list2)
# 第二种方法:使用列表生成式
list3 = [i**2 for i in range(1,6)]
print(list3) # [1, 4, 9, 16, 25]
# 使用列表生成式 生成1-10之间所有的奇数
list4 = [i for i in range(1,11) if i % 2 == 1]
print(list4)
# 使用列表生成式 生成1-10之间所有的奇数并且能被3整除的数字
list5 = [i for i in range(1,11) if i % 2 == 1 and i % 3 == 0]
print(list5)
# 列表生成式中使用双重循环
list6 = [i + j for i in "xyz" for j in "987"]
print(list6)
# 字典生成式:(了解)
dict1 = {i:i*i for i in range(1,6)}
print(dict1)
# 集合生成式:(了解)
set1 = {i*i for i in range(1,6)}
print(set1)
2.生成器
generator
next()
代码演示:
定义生成器: 只需要把列表生成式的[] 换成() 即可
g = (i ** 2 for i in range(1,10))
print(g)
print(type(g)) #<class 'generator'>
# 生成器得到的数据不能直接输出,要想访问里面的数据,必须使用next() 进行遍历,每调用一次next() 就会输出一个数据
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# 当通过next() 将生成器中的数据遍历完毕以后,接着调用next(),就会出现StopIteration
# print(next(g)) # StopIteration
# 生成器的应用场景:
'''
当需要生成无穷多的数据时,一般使用生成器. 若使用列表生成无穷多的数,会占用大量的空间,不合适.
'''
# 生成器相关的函数 yield
'''
1.yield存在于函数中,当普通函数中有了yield关键词,该普通函数变为了生成器函数.
2.调用生成器函数不会执行代码,需要使用next
3.可以在函数的内部不断地返回值,但是不会终止函数的执行(与return不同)
4.每次调用next以后,程序会在yield处暂停
'''
def test(m):
print("m=",m)
yield m * 2
print("m+1=",m+1)
yield (m + 1) * 2
print("m+2",m+2)
g = test(23) # 在普通函数test中加入了关键字yield,那该函数变成了生成器函数,直接调用不会执行.
print(type(g)) # <class 'generator'>
print(next(g)) # 函数执行到第一个yiled处暂停
print(next(g)) # 函数执行到第二个yiled处暂停
五、迭代器【掌握】
1.可迭代对象
可迭代对象【实体】:可以直接作用于for循环的实体【Iterable】
可以直接作用于for循环的数据类型:
a.list,tuple,dict,set,string
b.generator【() 和yield】
isinstance:判断一个实体是否是可迭代的对象
代码演示:
导入模块的方式:
第一种: import 模块名
第二种:from 模块名 import 函数
from fib import fibonacci 表示导入fib模块中的fibonacci 函数
# 使用可迭代对象 需要导入collections.abc
from collections.abc import Iterable
# 通过 isinstance:判断一个实体是否是可迭代的对象 返回值是bool类型,True或者False
from collections.abc import Iterable
# 可迭代对象:能够被for 循环遍历的实体就是可迭代对象
print(isinstance([],Iterable)) # True
print(isinstance((),Iterable)) # True
print(isinstance({},Iterable)) # True
print(isinstance("loha",Iterable)) # True
# 生成器
print(isinstance((i for i in range(1,10)),Iterable)) # True
# 列表\元组\字典\字符串\生成器 都是可迭代对象
print(isinstance(11,Iterable)) # False
print(isinstance(True,Iterable)) # False
# 整型\浮点型\布尔类型 都不是可迭代对象
2.迭代器
迭代器: 不但可以作用于for循环,还可以被next函数遍历【不断调用并返回一个元素,直到最后一个元素被遍历完成,则出现StopIteration】
目前为止,只有生成器才是迭代器【Iterator】
结论:迭代器肯定是可迭代对象,但是,可迭代对象不一定是迭代器
isinstance:判断一个实体是否是迭代器
代码演示:
from collections.abc import Iterator
# 迭代器:既能够通过 for循环遍历,也能next函数遍历的实体叫做迭代器.
# 目前只有生成器是迭代器
# 使用 isinstance() 判断某个实体是否是迭代器
print(isinstance([],Iterator)) #False
print(isinstance((),Iterator)) #False
print(isinstance({},Iterator)) #False
print(isinstance("loha",Iterator)) #False
print(isinstance(11,Iterator)) #False
print(isinstance(False,Iterator)) #False
# 只有生成器是迭代器
print(isinstance((i for i in range(1,10)),Iterator)) # True
3.可迭代对象和迭代器之间的转换
可以将 可迭代对象转换为迭代器:iter()
代码演示:
虽然list tuple str dict set 这些可迭代对象不能使用next() 函数遍历,但是可以通过iter() 函数将可迭代对象转换为迭代器.
# 可迭代对象转换为迭代器: iter()
list = [12,4,5,78]
# print(next(list)) # 'list' object is not an iterator
list1 = iter(list) # 将列表转换为 迭代器
print(next(list1)) # 12
print(next(list1)) # 4
print(next(list1)) # 5
print(next(list1)) # 78
总结:
a.凡是可以作用于for循环的对象都是Iterable类型
b.凡是可以作用于next函数的对象都是Iterator类型
c.list/tuple/dict/set/string都不是Iterator,可以通过iter()获得一个Iterator对象