04-Python的函数2
## 函数的作用域
- Python的作用域:
- 内置作用域
- 文件作用域
- 函数嵌套作用域
- 本地作用域
- 包含关系:内置作用域(文件作用域(函数嵌套作用域(本地作用域)))。
- 作用域外部的变量和函数可以之间在作用域内使用。
- 作用域域内的变量不能在域外直接使用。
- 按照作用域范围大小分类:
- 全局变量(global):在函数外部定义
- 内置作用域和文件作用域中定义的变量和函数都属于全局变量。
- 局部变量(local):在函数内部定义
- 嵌套作用域和本地作用域内定义的变量和函数都属于局部变量(本地变量)。
- 变量作用域就是变量的可访问范围,也称为命名空间。
- 第一次给变量赋值时,Python创建变量
- 第一次给变量赋值的位置决定了变量的作用域。
- 在同一个作用域中,变量名是唯一的。
- 在不同的作用域中,相同变量名也表示了不同的变量。
- 变量由作用范围限制:
- 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
- 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
- 调用函数时,所有在函数内声明的变量名称都将被加入到局部变量。
# 文件作用域 a, b = 5, 0 # a,e是一个全局变量 def sum(c, d): # c, d 是sum内的本地变量 f = 100 # 创建本地变量 e = c + d + a; # e在这里是局部变量,a是函数外面的全局变量 return e #调用sum函数 s = sum(10, 20) print(s) print ("函数外是全局变量 : ",b) # 结果 # 35 # 函数外是全局变量 : 0 """ 在该程序运行过程中,会产生a,b,c,d,f,e和sum 7个变量名。 a和e为文件作用域的全局变量 c,d,f,e是函数add内部的变量 """
# 遵循”本地“优先原则,外部作用域会被屏蔽 a = 100 # 全局变量 def addd(b): a = 0 # 局部变量,屏蔽全局变量a c = a + b return c print(addd(12)) # 结果 12
- global语句:
- 全局变量不经定义即可在函数内部使用。
- 在函数内部使局部变量为全局变量。
def Fun1(): global a a = 100 # a为全局变量 b =200 print(a) # a为全局变量,所以能够调用 # print(b) 会报错,因为b是Fun1内部的变量,无法调用 # 结果 100
a, b= 100, 12 def func(): global a # a是全局变量。 # 如果全局变量已经有这个a变量那就是指的它 如果全局没这个Num那就新定义一个全局变量。 a = 200 # 凡是在函数内部的变量Num 始终都是指全局变量。不存在有另外的局部变量叫Num的。 print(a) func() print(a) #输出200 说明修改的就是全局变量 def fun1(): global b b = 3 print(b) b = 120 # 对全局变量没有影响,新定义了一个变量b fun1() print(b) #输出3 说明新定义了一个全局+变量b # 结果 200 200 3 3
## 函数嵌套定义
- Python允许在函数内部定义函数。
- 内部定义的函数,也只能在函数内部使用
# 求直角三角形的斜边的平方 def Fun1(a,b): def Fun2(x): # 在Fun1内不定义函数Fun2 s = x*x return s s1 = Fun2(a)+Fun2(b) # 调用Fun2 return s1 # Fun2(5)会报错,外部无法调用,为局部变量 Fun1(3, 4) # 输出结果为20
## 偏函数
- 应用场景和理解:
- 函数在执行时,要带上所有必要的参数进行调用。
- 当一个函数的参数比较多时,有参数可以在函数被调用之前提前获知,即大部分情况下是一些固定的值。
- 为了简化调用函数,可以创建一个新函数
- 指定使用的函数的某个参数,为某个固定的值,这个新函数就是“偏函数”。
- 语法:
- 方式一:创建一个新的函数
- 方式二:通过 functools 模块调用 partial函数
- import functools
- NewFunc = functools.partial(函数,特定参数=指定值)
# 方式一 def Fun1(a, b, c, d=2): # d的值已经固定 print(a+b+c+d) Fun1(1,2,4) # 输出为 9 # 若想把c的值在接下里所有调用中一直固定为5 # 或者想修改d的值,接下里所有调用中都为修改的值 # 调用函数Fun1(1,2,c=5,d=3) # 若是每次都这样调用函数,参数都要重复写c=5,d=3 # 创建新的函数 def Fun2(a,b,c=5,d=3): Fun1(a,b,c,d) # 直接输入a,b的值,c,d已经被固定了 Fun2(1,2) # 输出为1+2+5+3=11 # Fun2就是一个偏函数
# 方式二 import functools def Fun1(a, b, c, d=2): # d的值已经固定 print(a+b+c+d) Fun1(1,2,3) # 输出为8 # 修改d的值 NewFun = functools.partial(Fun1,d=5) NewFun(1,2,3) # 输出为11 # 修改c,d的值 NewFun1 = functools.partial(Fun1,c=3,d=5) NewFun1(1,2) # 输出为11
## 递归函数
- 递归函数是指在函数体内调用函数的本身。
- 递归函数特性:
- 理论上讲递归函数会永远的执行下去,必须有一个明确的结束条件。
- 通常把一个大型复杂问题层层转化为一个与原问题相似的规模较小的问题来求解。
- 递归函数的优点是定义简单,逻辑清晰。
""" def story(): story() """# 理论会无限循环下去。。。 # 计算阶乘 n! = 1 * 2 * 3 * ..... def Fun1(n): if n == 1: return n elif n > 1: return n * Fun1(n - 1) else: return '请传递大于0的参数' print(Fun1(5)) # 输出为120
## 高阶函数
- 概念:当一个函数的参数,接受的又是另一个函数时,则把这个函数称为高阶函
def Fun1(a, b): return a+b def Fun2(a, b): return a-b def Fun3(a, b, fun): # 参数fun当做函数 res = fun(a, b) return res v = Fun3(1, 2, Fun1) print(v) # 输出3
- 系统内的一些高阶函数:
- map() :
- 根据提供的函数对指定序列做映射。
- 格式: map(function, iterable,...)
- 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
- 第二个参数iterable 指代一个或者多个课迭代对象
l1 = [i for i in range(20) if i%2==0] # 生成一个序列 l2 = [] # 定义一个空列表 for i in l1: l2.append(i*10) print(l2) # 利用map实现 def Fun1(i): return i*10 # 调用map函数 l3 = map(Fun1, l1) print(type(map)) print(l3) for i in l3: print(i,end = " ") # 结果 [0, 20, 40, 60, 80, 100, 120, 140, 160, 180] <class 'type'> <map object at 0x000001CD8AFE8CC0> 0 20 40 60 80 100 120 140 160 180
- reduce()
- 原意是归并,缩减。函数会对参数序列中元素进行累积,把一个可迭代对象归并成一个结果
- 对于作为参数的函数有要求:必须有两个参数,必须有返回结果
- reduce 需要导入functools包
- 格式:reduce(function, iterable[, initializer])
- function -- 函数,有两个参数
- iterable -- 可迭代对象
- initializer -- 可选,初始参数
- 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
from functools import reduce # 创建序列 l1 = [i for i in range(6)] # 相加函数 def MyAdd(x, y): return x + y rst = reduce(MyAdd, l1) # 0+1 +2 +3 +4 +5 =15 print(rst) # 输出15
- filter()
- 过滤函数:对一组数据进行过滤,符合条件的数据就会生成一个新的列表并返回
- 队列顺序不一定是一一对应的和map相反
- 格式:filter(function, iterable)
- function:判断函数
- iterable:可迭代对象
# 判断函数 def IsEven(a): return a%2 == 1 # a%2 == 1 是判断条件 l = [i for i in range(20)] # 创建序列 rst = filter(IsEven, l) # 调用filter print(rst, type(rst)) for i in rst: print(i,end = " ") # 结果 <filter object at 0x000001CD8AFE8AC8> <class 'filter'> 1 3 5 7 9 11 13 15 17 19
- sorted()
- 对可迭代对象照给定算法进行排序
- 格式:sorted(iterable[, cmp[, key[, reverse]]])
- iterable : 可迭代对象。
- cmp:比较的函数。
- key:排序前对每一个元素进行key函数运算
- reverse:排序规则,reverse = True 降序 , reverse = False 升序(默认)。
# 按照大小排序 a = [234,343,64,63,74,643] al = sorted(a, reverse=True) print(al) # 按绝对值进行排序 a = [-34,43,-456,5353,53] al = sorted(a, key=abs, reverse=True) print(al) # 结果 [643, 343, 234, 74, 64, 63] [5353, -456, 53, 43, -34]
## 返回函数
- 函数可以返回具体的值,也可以返回一个函数作为结果
# 被返回的函数在函数体内定义 def MyF2(): def MyF3(): print("fff3") return "这是返回内容" return MyF3 ## f = MyF2() print(type(f)) # <class 'function'> print(f) # <function MyF2.<locals>.MyF3 at 0x00000207E20D3F28> f() """ fff3 '这是返回内容' """ # 调用了MyF2()函数,就接着执行了MyF3()