Python之作用域

发布时间 2023-05-31 17:21:31作者: Way*yy

作用域、函数对象和闭包

作用域

1、全局作用域

内置名称空间+全局名称空间

全局存货 全局有效

2、局部作用域

局部名称空间

局部存活 局部有效

3、global关键字

作用:
	声明全局变量
    ###########################global

"""
    在函数的内部不能直接修改外部的变量
    1. 在函数的内部修改外部的不可变的数据类型需要使用global关键字声明
    2. 在函数的内部修改外部的可变类型的数据不需要使用global关键字的声明
"""

name_list = ['kevin', 'jason', 'tank']


def index():
    name_list.append('tony')


index()
print(name_list)  # 111 222


4、nonlocal
作用:

	声明变量来自外层函数不会去全局找
    """
    用的很少
    nonlocal的使用:
    1. 在函数内部的局部修改外部的局部的不可变类型的数据使用关键字nonlocal关键字声明
    2. 在函数内部的局部修改外部的局部的可变类型的数据不需要使用关键字nonlocal声明
"""
    
#######################nonlocals
def outer():
    name_list = ['kevin', 'tank']

    def inner():
        name_list.append('tony')
        print('inner')

    inner()
    print(name_list)  # 1  2  ['kevin', 'tank', 'tony']

outer()

函数对象

作用

1、可以被引用(赋值)

2、可以当做容器类型的元素(优化if分支结构)

3、可以当做参数传给另一个函数

4、可以当做函数的返回值

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

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

"""函数名就是函数的内存地址"""
print(globals())  # 'index': <function index at 0x00000123F32BE310> value值就是函数的内存地址
print(index) # <function index at 0x000001EB90491F28>
index() # 直接调用函数
a = index
a()  # index()

###############################################################################

# 2. 函数名也可以当成函数的实参
def index():
    print('from index')


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


func(index)

###############################################################################

# 3. 函数名也可以当成函数的返回值
def index():
    print('from index')


def func():
    print('from func')
   # return index()  # None
    return index


func()
res = func() # indaex()
print(res)
res()
# res = func()
# res()
# 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函数

# 应用案例
# 案例:把注册、登录功能封装成函数版本
def register():
    print('register')


def login():
    print('login')


def transfer():
    print('login')


def withdraw():
    print('login')


def shopping():
    print('login')
def shopping1():
    print('login')

func_dict = {
    '1': register,
    '2': login,
    '3': transfer,
    '4': withdraw,
    '5': shopping,
    '6': shopping1
}
while True:
    print("""
        1. 注册功能
        2. 登录功能
        3. 转账功能
        4. 提现功能
        5. 购物功能
    """)
    choice = input('请输入你的选择:').strip()
    if choice in func_dict:
        # func_name = func_dict.get(choice)
        # func_name()
        func_dict.get(choice)()

函数嵌套

1、定义

隐藏代码在函数外部无法看见这段代码

2、调用

举例:比较四个数的大小,嵌套多个函数每层函数比较两个数的大小
# 1. 定义一个函数,功能是比较两个数的大小
def my_max(a, b):
    if a > b:
        return a
    return b
# 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)

闭包函数

1、定义

闭       该函数是定义在函数内的函数

包       该函数引用了一个外层函数作用域的名字

2、内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用
	
    用途:给函数传参数
    
###############################################################################

def outer(a, b):
    # a = 1
    # b = 10

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

    return my_max


res=outer(2, 20)  # my_max的内存地址,res----->my_max
print(res())  # my_max()
print(res())  # my_max()
print(res())  # my_max()
res1 = outer(3, 30)
print(res1())
print(res1())
print(res1())
'''一次传值,多次调用'''

装饰器

1、为什么要用装饰器

1.1、为程序提供扩展功能的可能性

1.2、要遵循开放封闭原则

1.3、禁止修改原代码,但是可以新增功能

1.4、也不能修改调用方式

2、什么是装饰器

2.1为被装饰对象添加新功能的工具

2.2、不修改被装饰对象源代码和调用方式

3、装饰器的核心思想

3.1、就是在"不改变被装饰对象"内部的代码和"原有调用方式"的基础之上再"添加额外的功能"

4、装饰器的实现

实现原理:
	函数嵌套+闭包+函数对象
    
###############################################################################    
# 背景知识
def index():
    print("from index")
index()
# 现在让你统计index函数执行完毕之后的执行时间

# 时间模块
import time  # 内置模块,可以直接拿来使用

def index():
    time.sleep(3)
    print('from index')
# 1. 在函数执行之前打印一个时间点
start_time = time.time()
index()

# 2. 在函数执行完毕之后在打印一个时间点
end_time = time.time()

# 3. 两者的差就是函数的执行时间
print("index函数一共执行了:%s秒" % (end_time - start_time))
这样一个最low逼的装饰器就做好了