leonZhang123

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

day11

上周内容回顾

# 【一】垃圾回收机制 (GC机制)
# 在程序运行过程中会产生很多没用的数据,这些数据会占用计算机的内存空间、
# 于是 Python解释器为了解决垃圾占用的问题 自带了一个垃圾回收机制

# 引用计数 : 当变量值被变量名引用的时候次数就+1 当没有变量名引用当前变量的时候 引用次数就是 0
# 标记清除 : 当变量值不被引用的时候 会被垃圾回收机制不断扫描 频繁地扫描到一个变量值得时候 就会将其标记
# 分代回收 : 标记到一定次数的时候就会让其分代

# 【二】深浅拷贝
# 浅拷贝 copy 会将原对象复制成一个新的对象 但是新对象会引用原对象的可变数据类型的地址 [1,2,[3,4]] --> [1,2,[3,4,5]] ---> 旧的变新的也跟着变
# 深拷贝 copy.deepcopy 会将原对象复制成一个新的对象 并且新对象不会引用原对象的可变数据类型的值 [1,2,[3,4]] --> [1,2,[3,4,5]] ---> 旧的变但是新的不变

# 【三】文件操作语法
# 【1】打开文件的两种方式
# fp = open(文件地址,操作模式,编码格式)
# fp.read() / fp.write()
# fp.close() 需要自己主动关闭文件

# 使用解释器自带的 with 语句 --> 解释器会自动打开文件并且在最后结束的时候自动关闭当前文件
# with open("文件地址","操作模式", "编码格式") as fp:
#     fp.write()

# 【2】操作文件的方式
# r : read 读模式
'''
当读取的文件不存在的时候会直接报错
'''
# w : write 写模式
'''
当写入的文件没有的时候会自动创建当前文件 然后写入内容
每一次新打开文件后都会,将原本内容清空 ,然后在写入新的内容
'''
# a : append 追加模式
'''
当写入的文件没有的时候会自动创建当前文件 然后写入内容
每一次新打开文件后都会,在文件的结尾位置向后写入新的内容
'''

# w+ / a+ / r+ : 扩展模式 原本只有一个功能 变成了读写模式

# wb / rb : 读取和写入二进制数据的操作方式

# 【2】文件的操作方法
# read
'''
fp.read() : 一次性读取文件中的所有内容
fp.read(n) : 一次性读取n个字节的内容
fp.readline() : 一次性读取一行数据
fp.readlines() : 一次性读取所有行数据 并且将每一行数据放到一个列表中
'''
# write
'''
fp.write() : 一次性写入内容
fp.writelines(列表) : 一次性写入多个数据 先将列表中的每一个元素首尾拼接 再一次性写入全部数据
'''

'''
fp.readable() : 判断当前句柄对象是否可读
fp.writable() : 判断当前句柄对象是否可写
'''

# 【3】控制文件内指针的移动
# fp.tell() 查看当前所在的字节位置
# fp.seek(字节数,模式) 一后面的模式移动指定字节数
# 字节数是正数就是向后移动 如果是负数就是向前移动

# 0 : 相对于文件开头向后移动指定字节数据
# 1 : 相对当前字节位置向后移动指定字节数, 二进制数据中才会生效
# 2 : 相对于文件结尾向前移动指定字节数

# 【四】异常捕获机制
# 在程序运行过程中可能会随时发生错误导致程序崩溃
'''
try:
    正常执行的代码快
except  异常类型:
    异常处理的方法
else:
    正常代码走完才会继续走的代码
finally:
    无论报不报错都会走的代码
    
except 异常类型 as e:
    异常处理的方法
except (异常类型1,异常类型2) as e:
    异常处理的方法
except Exceptions as e:
    异常处理的方法
    
    
# 主动抛出异常 raise assert 
# raise 异常类型(异常信息)
# assert 条件表达式,错误信息
'''

# 【五】推导式
# 列表生成式
# [变量 for 变量 in 可迭代对象 if 条件表达式]
# 字典推导式
# {变量1:变量2 for 变量1 in 可迭代对象 for 变量2 in 可迭代对象}

# 【六】函数
# 函数就是一系列代码的集合体
# 函数就相当于我们提前做好的工具

# 【1】函数定义语法
'''
def 函数名(参数):
    代码体
'''
# 【2】定义函数的语法
'''
# 1 无参无返回值函数
def 函数名():
    ...
# 2. 有参无返回值函数
def 函数名(参数):
    ...
# 3. 有参有返回值的函数
def 函数名(参数):
    return 返回值
'''

# 【3】函数的调用方式
# 直接调用 直接函数名()
# 间接调用 新的变量名=函数名  ---> 新的变量名()
# 表达式调用 可以将函数的返回值作为表达式的一部分 res = add(1,2,3) + 9
# 函数作为参数 add(add(1,2),9)

# 【4】函数的参数
# (1)分为两类
# 实参 : 实际在调用函数的时候传入的确定的值
# 形参 : 在函数定义阶段放在函数的名字后面的参数名
# (2)根据传值方式的不同
# 位置参数 : 在函数调用的时候传递参数的时候按照变量名定义的顺序依次传值
# 关键字参数 : 在函数调用的时候传递参数的时候按照变量名的名字传值
# (3)指定默认值
# 默认参数 : 在函数定义阶段在变量名后面加上赋值、
# (4)可变长参数
# 在调用函数的时候可能会传入额外的参数
# 可变长位置参数 : *args 在函数调用的时候传入的额外的参数都会以元祖的形式被 args 接收到
# 可变长关键字参数 : **kwargs 在函数调用的时候传入的额外的关键字参数都会以字典的形式被 kwargs 接收到

上周作业完善

# 【一】分析功能
# 增加员工 --- 管理员才能增加员工
# 删除员工 --- 管理员才能删除员工
# 查看员工信息 --- 如果是登陆的自己的账号只能查看自己的 (用户身份) 如果是管理员 可以选择查看谁的账号信息
# 查看所有员工信息 -- 管理员才能做
# 修改员工信息 ---  如果是登陆的自己的账号只能查看自己的 (用户身份) 如果是管理员 可以选择查看谁的账号信息
# 文件拷贝 -- 管理员能做

# 【二】分功能开发
# 增加员工 append_user_info
# 删除员工 delete_user_one_info
# 删除员工 delete_user_all_info
# 查看所有人信息 view_user_all_info
# 查看指定信息 view_user_one_info
# 修改指定信息 update_user_info
# 文件复制拷贝 copy_file

# 【三】定义主框架逻辑
# 【1】定义功能菜单 --- 让用户进入系统的时候看到有哪些功能
# 【2】定义功能字典 --- 让用户选择的ID和指定的功能对应上
# 【3】定义主题逻辑
# (1)打印功能菜单
# (2)让用户选择功能ID
# (3)根据ID找到指定功能
# (4)执行指定功能

import os

# 全局登陆字典
login_dict = {
    "username": None,
    "role": None
}


# 数据处理函数
def handle(file_path="user_info.txt", mode="r", encoding="utf-8", data=None):
    '''

    :param file_path: 存储数据的文件名
    :param mode: 操作模式
    :param encoding: 编码格式
    :param data: 写数据需要的原始数据字典
    :return:
    '''
    if mode == "r":
        user_data_all = {}
        try:
            with open(file=file_path, mode=mode, encoding=encoding) as fp:
                for line in fp:
                    username, password, age, role, hobby = line.strip().split("|")
                    hobby_list = hobby.split(", ")
                    user_data_all[username] = {
                        "username": username,
                        "password": password,
                        "age": age,
                        "hobby": [item for item in hobby_list if len(item) != 0],
                        "role": role
                    }
        except Exception as e:
            print(f"欢迎第一次注册!")
        return user_data_all
    elif mode == "w":
        user_info_data_list = []
        for user_info_small_dict in data.values():
            hobby_list = user_info_small_dict.pop("hobby")
            hobby = ', '.join(hobby_list)
            user_info_small_dict.update(hobby=hobby)
            user_info_data = '|'.join([str(item) for item in user_info_small_dict.values()])
            user_info_data_list.append(user_info_data + "\n")
        # (2)保存用户信息
        with open(file=file_path, mode=mode, encoding=encoding) as fp:
            fp.writelines(user_info_data_list)


def get_username_password():
    username = input("请输入用户名 :>>>> ").strip()
    password = input("请输入密码 :>>>> ").strip()
    return username, password


def input_hobby():
    hobby_list = []
    while True:
        hobby = input("请输入爱好(q退出) :>>>> ").strip()
        if hobby == "q":
            print(f"当前输入爱好结束!")
            break
        if not hobby:
            continue
        if hobby in hobby_list:
            print(f"当前输入爱好重复!")
            continue
        else:
            hobby_list.append(hobby)
            print(f"当前输入爱好 {hobby} 已添加!当前已有爱好 :>>>> {', '.join(hobby_list)}")
    return hobby_list


def input_age():
    # 加一个 年龄 , 爱好
    age = input("请输入年龄 :>>>> ").strip()
    if not age.isdigit():
        return False, f"当前年龄非法!不是数字!"
    age = int(age)
    if age < 0 or age > 150:
        return False, f"当前年龄已超出正常人类范畴!"
    return True, age


def register():
    print(f"欢迎来到注册功能!")
    # 【1】让用户输入用户名和密码
    username, password = get_username_password()
    flag, age = input_age()
    if not flag:
        return flag, age
    hobby_list = input_hobby()
    if username == "dream" and password == "521":
        role = "admin"
    else:
        role = "user"
    # 加一个 身份信息
    # 【2】判断一下当前用户是否存在
    user_data_all = handle()
    user_info = user_data_all.get(username)
    # 【3】如果用户存在让用户去登录
    if user_info:
        return False, f"当前用户 {username} 已存在!请去登录!"
    # 【4】如果用户不存在 让用户注册
    user_data_all[username] = {
        "username": username,
        "password": password,
        "age": age,
        "hobby": hobby_list,
        "role": role
    }
    # (1)拼接信息
    handle(mode="w", data=user_data_all)
    # 【5】注册成功返回注册成功信息
    return True, f"用户 {username} 注册成功!"


# print(register())
# data = handle()
# print(data)


def login():
    print(f"欢迎来到登陆功能!")
    # 【1】让用户输入用户名和密码
    username, password = get_username_password()
    # 【2】查询到所有人的用户信息
    user_data_all = handle()
    # 【3】查询到当前登录这个人的登录信息
    user_info = user_data_all.get(username)
    # 【4】校验当前用户是否存在
    if not user_info:
        return False, f'当前用户 {username} 不存在 请先注册!'
    # 【4】校验当前登录的用户名和密码是否正确
    if user_info.get("password") != password or username != user_info.get("username"):
        return False, f'当前用户 {username} 用户名或密码错误 请重新输入!'
    # 【5】正确登录成功保存用户状态
    login_dict.update({
        "username": user_info.get("username"),
        "role": user_info.get("role")
    })
    # 【6】错误登录返回错误信息
    return True, f'当前用户 {username} 登陆成功!'


def append_user_info():
    # 【1】先校验当前登录用户的身份信息 ---> 管理员才能添加用户信息
    if login_dict.get("role") != "admin":
        return False, f"当前用户 {login_dict.get('username')} 没有权限添加用户信息!"
    print(f"欢迎当前管理员 {login_dict.get('username')} 访问添加用户信息!")
    # 【2】让管理员输入档期啊男用户的信息
    username, password = get_username_password()
    hobby_list = input_hobby()
    flag, age = input_age()
    if not flag:
        return flag, age
    role = input("请输入当前员工身份 (1 admin / 0 user) :>>>> ").strip()
    if role not in ["1", "0"]:
        return False, f'当前角色信息ID不存在!'
    if role == "1":
        role = "admin"
    elif role == "0":
        role = "user"
    # 【3】校验当前用户信息是否存在
    user_data_all = handle()
    # user_info = user_data_all.get(username)
    # if user_info:
    #     return False, f'当前用户 {username} 信息已存在!'
    if username in user_data_all.keys():
        return False, f'当前用户 {username} 信息已存在!'
    # 【4】用户信息不存在的时候新增用户信息
    user_data_all[username] = {
        "username": username,
        "password": password,
        "age": age,
        "hobby": hobby_list,
        "role": role
    }
    # (1)拼接信息
    handle(mode="w", data=user_data_all)
    # 【5】注册成功返回注册成功信息
    return True, f"添加用户 {username} 成功!"


def delete_user_one_info():
    print(f"欢迎来到删除指定员工功能!")
    # 只有登录用户才可以查看所有人的信息
    if not login_dict.get("username"):
        return False, f'当前用户未登录!请先登陆!'
    # 【一】让用户知道当前用户有哪些
    user_data_all = handle()
    user_id_dict = {}  # {"00001":"dream","00002":"hope"}
    count = 0
    for username, user_info_dict in user_data_all.items():
        count += 1
        index = str(count).zfill(5)  # 00001
        print(f'当前用户 ID :>>>> {index} 用户名 :>>>> {username}')
        user_id_dict[index] = username
    # 【二】让用户根据指定的标志获取到指定人的用户信息
    user_id = input("请输入您要查看的用户ID :>>>> ").strip()  # 00001
    user_name_true = user_id_dict.get(user_id)  # dream
    user_info_dict = user_data_all.get(user_name_true)
    if not user_info_dict:
        return False, f'当前查询用户ID {user_id} 对应的 用户 {user_name_true} 不存在'
    user_data_all.pop(user_name_true)
    # 因为自己已经被注销了 所以不能保持当前的登陆状态
    if user_name_true == login_dict.get("username"):
        login_dict.clear()
    handle(mode="w", data=user_data_all)
    return True, f"删除指定 用户 {user_name_true} 成功!"


def delete_user_all_info():
    print(f"欢迎来到删除所有员工功能!")
    if not login_dict.get("username"):
        return False, f'当前未登录!请先登陆!'
    if login_dict.get("role") != "admin":
        return False, f'当前用户 {login_dict.get("username")} 无权删除数据!'
    user_data_all = handle()
    user_data_all.clear()
    with open("user_info.txt", "w", encoding="utf-8") as fp:
        fp.write('')
    return True, f"删除所有 用户成功!"


def view_user_all_info():
    print(f"欢迎来到查看所有人信息功能!")
    # 只有登录用户才可以查看所有人的信息
    if not login_dict.get("username"):
        return False, f'当前用户未登录!请先登陆!'
    # 【一】获取到所有人的用户数据
    user_data_all = handle()
    # 【二】遍历所有人的用户数据进行格式化输出
    for username, user_info_dict in user_data_all.items():
        role = "管理员" if user_info_dict.get("role") == "admin" else "用户"
        print(f'''
        ############# 当前 {role} {username} 信息如下 ############# 
                        用户名 :>>>> {username}
                        年 龄  :>>>> {user_info_dict.get("age")}
                        爱 好  :>>>>{', '.join(user_info_dict.get("hobby"))}
        ############# 当前 {role} {username} 信息如上 ############# 
        ''')
    role = "管理员" if login_dict.get("role") == "admin" else "用户"
    return True, f'当前 {role} {login_dict.get("username")} 查看全部用户信息成功!'


def view_user_one_info():
    print(f"欢迎来到查看指定信息功能!")
    # 只有登录用户才可以查看所有人的信息
    if not login_dict.get("username"):
        return False, f'当前用户未登录!请先登陆!'
    # 【一】让用户知道当前用户有哪些
    user_data_all = handle()
    user_id_dict = {}  # {"00001":"dream","00002":"hope"}
    count = 0
    for username, user_info_dict in user_data_all.items():
        count += 1
        index = str(count).zfill(5)  # 00001
        print(f'当前用户 ID :>>>> {index} 用户名 :>>>> {username}')
        user_id_dict[index] = username
    # 【二】让用户根据指定的标志获取到指定人的用户信息
    user_id = input("请输入您要查看的用户ID :>>>> ").strip()  # 00001
    user_name_true = user_id_dict.get(user_id)  # dream
    user_info_dict = user_data_all.get(user_name_true)
    if not user_info_dict:
        return False, f'当前查询用户ID {user_id} 对应的 用户 {user_name_true} 不存在'
    # 【三】格式化输出当前制定人的信息
    role = "管理员" if user_info_dict.get("role") == "admin" else "用户"
    print(f'''
    ############# 当前 {role} {user_name_true} 信息如下 ############# 
                    用户名 :>>>> {user_name_true}
                    年 龄  :>>>> {user_info_dict.get("age")}
                    爱 好  :>>>>{', '.join(user_info_dict.get("hobby"))}
    ############# 当前 {role} {user_name_true} 信息如上 ############# 
        ''')
    return True, f'当前 {role} {login_dict.get("username")} 查看指定 用户 {user_name_true} 信息成功!'


def update_user_info():
    print(f"欢迎来到修改指定信息功能!")
    # 只有登录用户才可以查看所有人的信息
    if not login_dict.get("username"):
        return False, f'当前用户未登录!请先登陆!'
    # 【一】让用户知道当前用户有哪些
    user_data_all = handle()
    user_id_dict = {}  # {"00001":"dream","00002":"hope"}
    count = 0
    for username, user_info_dict in user_data_all.items():
        count += 1
        index = str(count).zfill(5)  # 00001
        print(f'当前用户 ID :>>>> {index} 用户名 :>>>> {username}')
        user_id_dict[index] = username
    # 【二】让用户根据指定的标志获取到指定人的用户信息
    user_id = input("请输入您要查看的用户ID :>>>> ").strip()  # 00001
    user_name_true = user_id_dict.get(user_id)  # dream
    user_info_dict = user_data_all.get(user_name_true)
    if not user_info_dict:
        return False, f'当前查询用户ID {user_id} 对应的 用户 {user_name_true} 不存在'
    print(f"如果不修改源数据请回车 :>>>> ")
    username = input("请输入用户名 :>>>> ").strip()
    password = input("请输入密 码 :>>>> ").strip()
    age = input("请输入年龄 :>>>> ").strip()
    if not age:
        age = user_info_dict.get("age")
    user_data_all[username].update({
        "username": username,
        "password": password,
        "age": age
    })

    # 保存数据
    handle(mode="w", data=user_data_all)
    return True, f'用户 {username} 信息修改成功!'


def check_self():
    username = login_dict.get("username")
    # 【一】校验当前用户登录
    if not username:
        return False, f'当前用户未登录!请先登录!'
    # 【二】校验当前登录的
    user_data_all = handle()
    user_info_dict = user_data_all.get(username)
    role = "管理员" if user_info_dict.get("role") == "admin" else "用户"
    print(f'''
    ############# 当前 {role} {username} 信息如下 ############# 
                    用户名 :>>>> {username}
                    密 码  :>>>> {user_info_dict.get("password")}
                    年 龄  :>>>> {user_info_dict.get("age")}
                    爱 好  :>>>>{', '.join(user_info_dict.get("hobby"))}
    ############# 当前 {role} {username} 信息如上 ############# 
        ''')
    return True, f'当前 {role} {login_dict.get("username")} 查看本人信息成功!'


def handle_data(file_path, file_type, tag, data=None):
    '''

    :param file_path: 需要读取或写入数据的绝对路径
    :param file_type: 当前的文件类型
    :param tag:  读或者写的标志
    :param data:  写数据时候的原始数据
    :return:
    '''
    text_file_list = ["txt", "text", "doc", "docx"]
    bytes_file_list = ["jpg", "png", "mp4", "mp3", 'bmp', 'gif', 'jpeg', 'png']
    mode_read = None
    mode_write = None
    # 根据当前的文件类型扩展性获取到指定的读模式和写模式
    if file_type in text_file_list:
        mode_read = "r"
        mode_write = "w"
    elif file_type in bytes_file_list:
        mode_read = "rb"
        mode_write = "wb"
    encoding = "utf-8" if mode_read == "r" else None
    if tag == "read":
        try:
            with open(file_path, mode_read, encoding=encoding) as fp:
                data = fp.read()
            return data
        except Exception as e:
            return ""
    elif tag == "write":
        with open(file_path, mode_write, encoding=encoding) as fp:
            fp.write(data)


def copy_file():
    print(f"欢迎来到文件复制拷贝功能!")
    original_path = input("请输入文件的源地址 :>>>> ").strip()
    file_path_list = original_path.split(os.sep)
    file_name_type = file_path_list.pop()
    original_name, original_file_type = file_name_type.split(".")
    file_data = handle_data(file_path=original_path, file_type=original_file_type, tag="read")
    if not file_data:
        return False, f'当前文件不存在!'
    target_path = input("请输入目标文件地址 :>>>> ").strip()
    file_name = input("请输入文件名(留空则使用源文件名) :>>>> ").strip()
    if not file_name:
        file_name = original_name
    file_name_type = file_name + '.' + original_file_type
    target_file_path = target_path + os.sep + file_name_type
    handle_data(file_path=target_file_path, file_type=original_file_type, tag="write", data=file_data)
    # 【六】返回信息
    return True, f'''
    已将源文件复制到指定地址
        源 地 址 :>>>> {original_path}
        目标地址 :>>>> {target_file_path}
    '''


# print(copy_file())

# 【一】定义一个主功能逻辑函数
func_menu = '''
***************** 员工管理系统 ***************** 
                    1.注册
                    2.登陆
                    3.查看指定用户信息
                    4.查看所有用户信息
                    5.修改指定用户信息
                    6.删除指定用户信息
                    7.删除所有用户信息
                    8.拷贝文件
                    9.添加员工信息
                    10.查看自己的信息
                    11.退出
***************** 员工管理系统 ***************** 
'''

func_dict = {
    "1": register,
    "2": login,
    "3": view_user_one_info,
    "4": view_user_all_info,
    "5": update_user_info,
    "6": delete_user_one_info,
    "7": delete_user_all_info,
    "8": copy_file,
    "9": append_user_info,
    "10": check_self,
    "11": "q",
}


def main():
    while True:
        print(func_menu)
        func_id = input("请输入功能ID :>>>> ").strip()
        if func_id not in func_dict:
            print(f"当前功能ID不存在!")
            continue
        func = func_dict.get(func_id)
        if func == "q":
            print(f"欢迎下次使用!")
            break
        flag, msg = func()
        if flag:
            print(msg)
        else:
            print(msg)
            continue


main()

【一】命名关键字参数

def add(x, y, z=6, *args, **kwargs):
    return x + y

# 定义在 add 后面的x 和 y 就是形形参 z 就是默认参数
# 可变长位置参数 *args
# 可变长关键字参数 **kwargs


# 命名关键字参数
# ● 想要限定函数的调用者必须以key=value的形式传值
#   ○ Python3提供了专门的语法:+
#     ■ 需要在定义形参时,用 * 作为一个分隔符号,* 号之后的形参称为命名关键字参数。
#   ○ 对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值

def add(x,y,*,z):
    print(z)

add(1,2,z=9)

【1】函数内判断

  • 在定义了**kwargs参数后,函数调用者就可以传入任意的关键字参数key=value
  • 如果函数体代码的执行需要依赖某个key,必须在函数内进行判断
def register(name, age, **kwargs):
    if 'sex' in kwargs:
        # 有sex参数
        pass
    if 'height' in kwargs:
        # 有height参数
        pass

【2】命名关键字参数

  • 想要限定函数的调用者必须以key=value的形式传值
  • Python3提供了专门的语法:+
  • 需要在定义形参时,用 * 作为一个分隔符号,* 号之后的形参称为命名关键字参数。
  • 对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值
def register(name, age, *, sex, height):  # sex,height为命名关键字参数
    pass


# 正确使用
register('Dream', 18, sex='male', height='1.8m')

# TypeError:未使用关键字的形式为sex和height传值
register('Dream', 18, 'male', '1.8m')

# TypeError没有为命名关键字参数height传值。
register('Dream', 18, height='1.8m')

【3】命名关键字参数默认值

  • 命名关键字参数也可以有默认值,从而简化调用
def register(name, age, *, sex='male', height):
    print('Name:%s,Age:%s,Sex:%s,Height:%s' % (name, age, sex, height))


register('Dream', 18, height='1.8m')
# Name:Dream,Age:18,Sex:male,Height:1.8m
  • 需要强调的是:sex不是默认参数,height也不是位置参数
  • 因为二者均在*后,所以都是命名关键字参数,形参sex=’male’属于命名关键字参数的默认值,因而即便是放到形参height之前也不会有问题。
  • 另外,如果形参中已经有一个*args了,命名关键字参数就不再需要一个单独的 * 作为分隔符号了
def register(name, age, *args, sex='male', height):
    print('Name:%s,Age:%s,Args:%s,Sex:%s,Height:%s' % (name, age, args, sex, height))


# sex与height仍为命名关键字参数
register('Dream', 18, 1, 2, 3, height='1.8m')
# Name:Dream,Age:18,Args:(1, 2, 3),Sex:male,Height:1.8m

【二】函数注解

【三】名称空间和作用域

# 【一】什么是名称空间
# 名称空间就是存放变量名和变量值映射关系的地方
# 【二】名称空间的分类
# 【1】内建名称空间
# 伴随着Python解释器运行而产生的名称空间
# 比如你所使用的 def if else 内置的关键字都是 Python解释器在启动的时候自动加载的
# 【2】全局名称空间
# 伴随着Python解释器启动,自己定义在.py文件中的变量都是放在全局名称空间中的
# 【3】局部名称空间
# 定义在函数或者类内部的变量名和变量值

# 【三】名称空间的加载顺序和查找顺序
# 加载顺序 内建 --- 全局 --- 局部
# 查找顺序 局部 --- 全局 --- 内建

# 【四】作用域
#  作用域就是变量名和变量值可以被访问的范围
# 其实就是你的变量名定义的位置和可以查找的位置

# 【1】作用域分为四类
# 局部作用域
# 全局作用域
# 内建作用域
# 内嵌作用域

# 【2】内建作用域
# ● Built-in(内置):解释器内置的变量,比如int, str等。
# ● 作用范围:所有模块(文件)
# ● Python中没有块级作用域。
# ● 块级作用域:代码块中的变量,比如if、while、for后面的代码

# 【3】全局作用域
# ● Global(全局):一般模块文件顶层声明的变量具有全局作用域,从外部来看,模
# 块的全局变量就是一个模块对象的属性,仅限于单个模块文件中。
# ● 作用范围:当前模块(文件)

# 【4】局部作用域
# ● Local(局部变量):暂时的存在,依赖于创建该局部作用域的函数。函数存,则局部变量存,函数亡,则局部变量亡。
# ● 作用范围:当前整个函数体范围

# 【5】内嵌作用域
# ● Enclosed(嵌套):一般是在函数中嵌套函数的时候,外层函数的变量作用域。
# ● 作用范围:闭包函数

# 【五】作用域声明
# 内建作用域里面提前加载好的 os
import os

# 自己在文件中定义的变量 全局作用域
'''

age = 18


def student():
    # 局部作用域:定义在函数或者类内部的所有变量
    age = 28
    print(f" student my age is {age}")

    def inner():
        # 内嵌作用域:在函数的函数内部定义的变量
        age = 38
        print(f"inner my age is {age}")
    inner()
student()
print(f"global my age is {age}")

'''

# 作用域的加载顺序
# 内建 -- 全局 -- 局部 -- 内嵌
# 查找循序 : 内嵌 -- 局部 -- 全局 -- 内建
# 查找顺序遵循一个规则 LEGB 规则
# L ---> local 局部的局部 内嵌
# E ---> enclosed 局部
# G ---> global 全局
# B ---> built-in 内建

user_dict = {
    "age": 99
}
age = 18


def func():
    # 使用关键字来提 高当前变量的级别
    # 局部修改全局不可变数据类型需要使用 global 提高当前作用域级别
    global age
    age = 19
    age_ = age
    print(f"func my age is {age}")
    print(f"func my age_ is {age_}")
    user_dict["age"] = 999

    def inner():
        # 提高内嵌函数作用域的变量级别
        nonlocal age_  # no binding for nonlocal 'age' found
        age_ = 38
        print(f"inner my age_ is {age_}")
        user_dict["age"] = 888

    inner()
    print(f"func my age_ is {age_}")


func()
print(f"global my age is {age}")
print(user_dict["age"])
# 字典是可变数据类型 ,大家对于修改字典的时候都是修改的同一块内容空间地址上面的值

# 【总结】
# 【1】名称空间就是存放变量名和变量值映射关系的地方 内建 全局 局部
# 【2】作用域就是变量名和变量值映射关系存放的范围 内建 全局 局部 内嵌
# 【3】如果局部修改全局不可变数据类型 用 global 提高当前作用域级别
# 如果是内嵌修改局部不可变数据类型 用nonlocal 提高作用域级别
# 内嵌作用域无法修改全局作用域中的不可变数据类型

【四】闭包函数

# 函数的调用方式
# 【1】直接调用
# 函数名()
# 【2】间接调用
# 新的变量名 = 函数名
# 新的变量名()

# 【3】作为表达式
# res = add(1,2) + 9

# 【4】作为函数的参数
# add(add(1,2),9)

# 【5】函数可以作为返回值
'''
login_dict = {}


def login():
    print(f"欢迎来到登陆功能")


def register():
    print(f"欢迎来到注册功能")


def main():
    if not login_dict.get("is_login"):
        return login
    else:
        return register

print(main()())
'''

'''
login_dict = {}


def login():
    print(f"欢迎来到登陆功能")


def register():
    print(f"欢迎来到注册功能")


def outer(func):
    print(f" func >>>>> {func}")  # <function login at 0x104797f40>

    def inner():
        print(f" inner func >>>>> {func}")
        # inner func >>>>> <function login at 0x10104bf40>
        if not login_dict.get("username"):
            func()

    return inner


print(outer(login)())
print(outer(register)())
# <function outer.<locals>.inner at 0x1163d5120>
'''

# 闭包函数
# 内嵌函数对外部函数作用域有引用的函数就叫闭包函数
'''
def outer(func):
    print(f" func >>>>> {func}")  # <function login at 0x104797f40>
    func = login
    def inner():
        print(f" inner func >>>>> {func}")
        # inner func >>>>> <function login at 0x10104bf40>
        if not login_dict.get("username"):
            func()

    return inner
'''

# 闭包函数最主要的应用场景 ---> 装饰器

# 看上一期视频预习一下闭包函数和装饰器推到过程
posted on 2026-06-05 19:23  leonZhang123  阅读(7)  评论(0)    收藏  举报