python 函数之作用域、闭包

发布时间 2023-05-29 15:59:09作者: 凡人半睁眼

一、查看全局变量和局部变量

1、globals ()

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fea80168710>, '__spec__': None, '__annotations__': \
{}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/sanpangdan/Desktop/python_fullstack/随机抽人.py', '__cached__': None, 'openpyxl': <module 'openpyxl' from \
'/Users/sanpangdan/Library/Python/3.6/lib/python/site-packages/openpyxl/__init__.py'>, 'random': <module 'random' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py'>,\
'workbook': <openpyxl.workbook.workbook.Workbook object at 0x7fea80c02978>, 'sheet': <Worksheet "Sheet1">, 'i': 27, 'j': 2, 'x': '钱家'}

2、locals()

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f7a50168710>, '__spec__': None, '__annotations__': \
{}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/sanpangdan/Desktop/python_fullstack/随机抽人.py', '__cached__': None, 'openpyxl': <module 'openpyxl' from \
'/Users/sanpangdan/Library/Python/3.6/lib/python/site-packages/openpyxl/__init__.py'>, 'random': <module 'random' from '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py'>, \
'workbook': <openpyxl.workbook.workbook.Workbook object at 0x7f7a50c02978>, 'sheet': <Worksheet "Sheet1">, 'i': 5, 'j': 2, 'x': ''}

二、名称空间的作用域

1、作用域:变量能够作用的范围

内置的名称空间

在程序的任何阶段任何位置都可以使用(全局有效)

全局的名称空间

在程序的任何阶段任何位置都可以使用(全局有效)

局部的名称空间

在函数内部有效(局部有效)

2、global和nonlocals关键字

global的使用:单个函数调用函数之外全局变量场景

在函数的内部不能直接修改外部的变量

  •  在函数的内部修改外部的不可变的数据类型(如字符串)需要使用global关键字声明
  •  在函数的内部修改外部的可变类型的数据(如列表)不需要使用global关键字的声明

nonlocal的使用:函数嵌套函数,内层函数调用外层函数场景

  • 在函数内部的局部修改外部的局部的不可变类型的数据使用关键字nonlocal关键字声明
  • 在函数内部的局部修改外部的局部的可变类型的数据不需要使用关键字nonlocal声明

三、函数对象:函数名

函数名的使用有四种用法

1. 函数名可以当成变量名来使用

函数名对应的就是一个内存地址

def index(): # index它是属于全局的
    print('index')

# """函数名就是函数的内存地址"""

print(index)

index() # 直接调用函数
a = index
a() # index()

2、函数名也可以当成函数的实参

def index():
    print('from index')

def func(func_name):
    print('from func')
    func_name() # 相当于是index()

func(index)

3. 函数名也可以当成函数的返回值

def func():
    print('from func')
# return index() # None
    return index
res=func() # res是函数的内存地址
res() # index()
print(res)

4、函数名也可以当成容器类型的元素

def index():
    print('from index')

# l = [1, 2, 3, index()]
l = [1, 2, 3, index] # [1, 2, 3, <function index at 0x0000021226FCE310>]
print(l)
l[3]() # 调用index函数

四、函数的嵌套使用

1、函数之间互相调用,函数里面调用函数
2、常用场景
定义一个函数,功能是比较两个数的大小

def my_max(a, b):
    if a > b:
        return a
    return b

# res = my_max(1, 10)
# print(res)

# 2. 定义一个函数,比较4个数的大小
def many_max(a, b, c, d):
    res = my_max(a, b)  # res是a和b中的最大的
    res1 = my_max(res, c)  # res1就是abc中的最大值
    res2 = my_max(res1, d)  # res2就是abcd中的最大值
    print(res2)
    return res2

ret=many_max(1, 2, 3, 4)
print(ret)

3、闭包函数

什么是闭包函数? (闭包函数是一个整体,只有同时满足闭和包的条件才算)
闭:闭就是函数内部定义函数,至少两层函数

def outer():
  def inner():
  pass

包:内部的函数使用外部函数名称空间中的名字

闭包函数使用场景?

闭包函数其实是给函数传参的第二种方式!

一次传参多次调用

def outer(a, b):
    def my_max():
        if a > b:
            return a  # 不同分支的 return
        return b

    return my_max

res = outer(2, 20)  # outer 函数不会直接执行my_max(my_max没有被调用),而是返回return my_max的函数名
print(res)  # my_max
print(res())  # my_max()
res1 = outer(3, 30)
print(res1)
print(res1())