函数式编程-高级
一、函数的参数类型
1. 不可变类型参数
不可变类型参数有:整数,字典,字符串
传递不可变类型参数,不会影响参数本身。
代码:
a = 100
print(f"函数外边a的id值----->{id(a)}")
print(f"a的值为{a}")
def func(b):
# a和b的id值相同
print(f"函数参数传递过来的id值----->{id(b)}")
print(f"b的值为:{b}")
# 修改b的值
b = 200
print(f"修改后b的id----->{id(b)}")
print(f"修改后b的值为:{b}")
func(a)
print(f"b值修改后,a的id值----->{id(a)}")
print(f"b值修改后,a的值:{a}")
结果:
函数外边a的id值----->140729229159920
a的值为100
函数参数传递过来的id值----->140729229159920
b的值为:100
修改后b的id----->140729229163120
修改后b的值为:200
b值修改后,a的id值----->140729229159920
b值修改后,a的值:100
2. 可变类型参数
可变类型参数有:列表、字典
传递可变类型参数,如果直接重新赋值,那么也不会影响参数本身,如果直接在原对象基础上进行
修改会影响。
代码:
list_outer = [1, 2, 3]
print("list_outer的值和id值:", list_outer, id(list_outer))
def func(list_inner):
print("list_inner的值和id:", list_inner, id(list_inner))
list_inner.append(4)
print("修改后list_inner的值和id:", list_inner, id(list_inner))
func(list_outer)
print("修改后list_outer的值和id值:", list_outer, id(list_outer))
结果:
list_outer的值和id值: [1, 2, 3] 1615815397768
list_inner的值和id: [1, 2, 3] 1615815397768
修改后list_inner的值和id: [1, 2, 3, 4] 1615815397768
修改后list_outer的值和id值: [1, 2, 3, 4] 1615815397768
二、命名空间
1. 概念
命名空间指的是保存程序中变量名和值的字典。字典的key是变量的名称,value是变量的值。
如:{“name”: “zr”, “age”:18}
2. 分类
局部命名空间:记录函数的变量。包括函数的参数和函数内定义的变量。
全局命名空间:记录模块(一个.py文件)的变量。包括函数、类、其他导入的模块。
内置命名空间:记录解释器内置的变量。任何模块都可访问它,包括内置的函数和异常。
3. 访问命名空间
locals():访问局部命名空间:根据调用的位置有关系
globals():访问全局命名空间:与调用位置无关
def func1(name, age):
"""命名空间的访问"""
num = 10
loc = locals() # 局部命名空间
print(loc) # {'name': 'tom', 'age': 18, 'num': 10}
func1("tom", 18)
glo = globals()# 全局命名空间
print(glo)
"""
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.sourcefileloader object at>,
'__spec__': None, '__annotations__': {}, '__builtins__': ,
'__cached__': None, 'func1': , 'glo': {...}}
"""
4. 命名空间的加载顺序
First:内置命名空间(程序运行前加载)
Second:全局命名空间(程序运行时加载)
Third:局部命名空间(程序运行中,函数被调用时才加载,当函数返回结果或抛出异常时,被删除。每个递归调用的函数都有自己的命名空间。)
5. 命名空间的查找顺序
局部命名空间 -------> 全局命名空间 --------> 内置命名空间
三、作用域,局部变量,全局变量
1. 概念
作用域:变量在程序中的可应用范围。
局部变量:在函数中定义的变量,只在函数内部生效。
全局变量:在程序一开始定义的变量,在整个程序中起作用。
2. 作用域的分类
Local(函数内部):局部作用域
Enclosing(嵌套函数的外层函数内部):嵌套作用域(闭包)
Global(模块全局):全局作用域
Built-in(内建):内建作用域
注意:
在Python中,模块(module),类(class)、函数(def、lambda)会产生新的作用域。而其他代码块不会,也就是说,类似分支语句、循环语句、异常捕捉等的变量是可以全局使用的。
3.全局变量和局部变量
全局变量是不可变数据类型,函数无法修改全局变量的值。
全局变量是可变数据类型,函数可以修改全局变量的值。
name = "zs" # 全局变量
def func(arg1):
name = "ls" # 局部变量
age = arg1
print(name) # zs
func(23)
# print(age) # 报错 NameError: name 'age' is not defined
四、global 和 nonlocal关键字
1. global
global关键字可以将局部变量变成一个全局变量。
格式: global 变量名
n = 20
def func():
global n # 将n声明为全局变量
n = n+1
print(n) # 21
func()
print(n) # 21
2. nonlocal
nonlocal关键字可以修改外层(非全局)变量。
注意:必须得是嵌套函数,nonlocal才会生效。
格式: nonlocal 变量名
def func():
age = 20
def inner():
# global age # 函数外无age变量,声明为全局变量会错误
nonlocal age # 将内层变量age声明为外层age
age = age + 1
print(age) # 21
inner()
print(age) # 21
func()