【2022-07-04】python函数以及名称空间与作用域

python函数以及名称空间与作用域

函数参数补充

*与**在实参中的作用

*号在实参中,会将*号后面的数据类型,用for循环的方式依次进行取值,并传输给函数使用,数据类型可以是列表、字符串、字典、元组,

其中字典在取值的时候,只有键会参与,值不参与

**只针对字典,它会将字典的键值对取出来,当成关键字参数的形式传输给函数

 
def function(*args, **kwargs):
    print(args)
    print(kwargs)


function()                                      # ()   {}
function([11, 22, 33, 44, 55])                  # ([11, 22, 33, 44, 55],)   {}

l1 = [66, 77, 88, 99, 123]
function(l1[0], l1[1], l1[2], l1[3], l1[4])     # (66, 77, 88, 99, 123)   {}
function(*l1)                                   # (66, 77, 88, 99, 123)   {}

s1 = 'good job'
function(*s1)                                   # ('g', 'o', 'o', 'd', ' ', 'j', 'o', 'b')     {}

dict1 = {'1': '张三', '2': '30'}
function(*dict1)                                # ('1', '2')   {}

dict2 = {'username': '李四', 'pwd': 666} 
function(**dict2)                               # ()  {'username': '李四', 'pwd': 666}
function(username='李四', pwd=666)              # ()  {'username': '李四', 'pwd': 666}

命名关键字参数

命名关键字参数需要放在形参*args的后面,形参**kwargs的前面,不然就会报错

def function(x, y, *args, z):
    print(x, y, args, z)


function(11, 22, 33, 44, 55, 66)              # 报错:TypeError: function() missing 1 required keyword-only argument: 'z'
function(11, 22, 33, 44, 55, z=666)           # 11 22 (33, 44, 55) 666


def function(x, y, *args, z, **kwargs):
    print(x, y, args, z, kwargs)


function(11, 22, 33, 44, 55, z=777, name='张三', age=888)  # 11 22 (33, 44, 55) 777 {'name': '张三', 'age': 888}

名称空间与作用域

名称空间

名称空间就是用来存放变量名与数据值之间绑定关系的地方

username = '张三'

首先在内存中申请一块内存空间用于存储数据值张三,然后绑定给变量名username

变量名username与数据值张三的绑定关系就会存储到名称空间里,后续如果需要使用变量名都是去名称空间里查找并锁定对应的数据值

del username 删除的不是数据值,而是变量名以及变量名与数据值之间绑定的关系

username = '张三'
print(username)
print(username)
print(username)



del username
print(username)           #  NameError: name 'username' is not defined

名称空间的分类

内置名称空间

python解释器运行就会创建的名称空间,写代码过程中可以直接使用的名字都在该空间内。eg: len() print() input().....

全局名称空间

py文件运行代码过程中产生的名字都会存入该名称空间,如逻辑代码的变量名,分支结构的变量名,循环结构的变量名,以及定义函数的函数名

局部名称空间

函数体代码运行过程中产生的名字都会存入该名称空间

名字的查找顺序

查找名字之前一定要先看自己在哪个名称空间

1.当前在全局名称空间
	全局名称空间	 >>>:   内置名称空间
2.当前在局部名称空间
	局部名称空间   >>>:  全局名称空间  >>>:	内置名称空间
名字的查找顺序默认情况下不能颠倒只能是	局部>>>:全局>>>:内置
名字的存活周期
存活周期
  1.内置名称空间
  	python解释器运行 产生
    python解释器关闭 销毁
  2.全局名称空间
  	py文件开始运行 产生
    py文件运行结束 销毁
  3.局部名称空间
  	函数体代码开始运行 产生
    函数体代码运行结束 销毁

作用域

1.内置名称空间
	在程序任意位置都可以使用(全局有效)
2.全局名称空间
	在程序任意位置都可以使用(全局有效)
3.局部名称空间
	在各自的局部空间可以使用(局部有效)

global与nonlocal关键字

gloabl关键字:局部修改全局不可变类型
# x = 111
# def index():
#     # x = 222  # 并不是在修改全局的x 而是在局部名称空间中创建了一个新的x
#     # 如果想要在局部名称空间中修改全局名称空间中的名字 那么需要使用关键字申明
#     global x  #  修改的是全局x而不是产生新的x
#     x = 666
# index()
# print(x)

l1 = [111, 222, 333]
def index():
    l1.append(444)
index()
print(l1)
"""
如果想要在局部修改全局的不可变类型
    需要提前加关键字global申明
如果想要在局部修改全局的可变类型
    不需要加关键字global申明
"""

def index():
    x = 111  # 在index的局部产生一个x=111
    l1 = [11, 22, 33]
    def f1():
        # x = 222  # 在f1的局部产生一个x=222
        # print(x)
        # 局部名称空间嵌套 内层修改外层
        # nonlocal x
        # x = 333
        l1.append(44)
    f1()
    print(x)
    print(l1)
index()

局部名称空间嵌套的情况下 内层如果想要修改外层
    情况1数据是不可变类型
        需要使用关键字nonlocal
    情况2数据是可变类型
        不需要使用关键字nonlocal

局部名称空间的复杂情况

x = 111
如果函数没有被调用 那么不要去管函数体代码有多复杂,先跳过
def f1():
    x = 222
    def f2():
        x = 333
        def f3():
            print(x)  # 检测语法的时候 发现f3的局部名称空间将来会有x 所以查找的时候就跟f3的局部名称空间要(特例 可以忽略)
            x = 444 
            # print(x)
        f3()
    f2()
f1()


局部名称空间之间如果不是嵌套关系 那么互不干涉!!!
def index1():
    name = 'jason'
def index2():
    age = 18
    print(name)  # 报错
index1()
index2()

函数名的多种使用方式

# def index():
#     print('from function index')
# 用法1:函数名可以当做变量名赋值
# print(index)
# res = index  # 让res也指向函数体代码
# print(res)
# res()  # index()

# 用法2:函数名还可以当成函数的实参
# def index():
#     print('from index')
# def func(a):
#     print('from func')
#     print(a)
#     a()
# func(index)

# 用法3:函数名还可以当做函数的返回值
# def func():
#     print('from func')
#     return index  # 将函数名当做返回值
# def index():
#     print('from index')
# res = func()  # res接收函数名
# print(res)  # 指向的是index函数的内存地址
# res()  # index()

# 用法4:函数名可以作为容器类型的元素
'''容器类型:内部可以存放多个元素的数据类型>>>:列表、元组、字典'''
# def index():
#     print('from index')
# l1 = [11, 22, 33, 44, index]
# print(l1)
# l1[-1]()  #  index()

课题演练

# 4.定义存储用户数据的字典
data_dict = {}  # {'1':{}, '2':{}, '3':{} }

'''1.先封装成五个空函数'''
def add_emp_info():
    while True:
        # 5.获取用户数据
        emp_id = input('请输入员工编号>>>:').strip()
        # 9.针对员工编号应该做不重复校验
        if emp_id in data_dict:
            print('该员工编号已经存在')
            continue
        emp_name = input('请输入员工姓名>>>:').strip()
        emp_age = input('请输入员工年龄>>>:').strip()
        emp_job = input('请输入员工岗位>>>:').strip()
        emp_salary = input('请输入员工薪资>>>:').strip()
        # 6.构造存储用户数据的小字典
        temp_dict = {}
        # 7.将员工数据全部录入该小字典
        temp_dict['emp_id'] = emp_id
        temp_dict['emp_name'] = emp_name
        temp_dict['emp_age'] = emp_age
        temp_dict['emp_job'] = emp_job
        temp_dict['emp_salary'] = emp_salary
        # 8.将员工数据小字典当做大字典的值添加
        data_dict[emp_id] = temp_dict  # {'1':{}}
        break

def edit_emp_salary():
    while True:
        # 1.获取员工编号
        target_emp_id = input('请输入想要修改的员工编号>>>:').strip()
        # 2.判断当前员工编号是否存在
        if target_emp_id not in data_dict:
            print('当前员工编号不存在 无法修改!!!')
            continue
        # 3.根据员工编号获取该员工的详细数据(小字典)
        emp_data = data_dict.get(target_emp_id)  # {}
        # 4.获取新的员工薪资
        new_salary = input('请输入该员工新的薪资>>>:').strip()
        # 5.修改员工小字典中薪资对应的值
        emp_data['emp_salary'] = new_salary
        # 6.将修改之后的小字典重新赋值到大字典中
        data_dict[target_emp_id] = emp_data
        # 7.人性化提示(也可以不写)
        print(f'员工编号:{target_emp_id} 员工姓名:{emp_data.get("emp_name")}薪资修改成功')
        break

def check_emp_info():
    while True:
        # 1.获取员工编号
        target_emp_id = input('请输入想要查询的员工编号>>>:').strip()
        # 2.判断当前编号是否存在
        if target_emp_id not in data_dict:
            print('当前员工编号不存在')
            continue
        # 3.根据员工编号获取员工数据字典
        emp_data = data_dict.get(target_emp_id)
        # 4.格式化输出员工数据
        print(f"""
                --------------------emp of info------------------
                编号:{emp_data.get('emp_id')}
                姓名:{emp_data.get('emp_name')}
                年龄:{emp_data.get('emp_age')}
                岗位:{emp_data.get('emp_job')}
                薪资:{emp_data.get('emp_salary')}
                -------------------------------------------------
                """)
        break

def check_all_emp():
    # 1.获取所有员工数据小字典
    all_emp_data = data_dict.values()  # [{},{},{}]
    # 2.循环获取每一个员工数据字典
    for emp_data in all_emp_data:  # {}
        # 4.格式化输出员工数据
        print(f"""
                        --------------------emp of info------------------
                        编号:{emp_data.get('emp_id')}
                        姓名:{emp_data.get('emp_name')}
                        年龄:{emp_data.get('emp_age')}
                        岗位:{emp_data.get('emp_job')}
                        薪资:{emp_data.get('emp_salary')}
                        -------------------------------------------------
                        """)

def delete_emp_info():
    while True:
        # 1.获取想要删除的员工编号
        target_delete_id = input("请输入想要删除的员工编号>>>:").strip()
        # 2.判断员工编号是否存在
        if target_delete_id not in data_dict:
            print('员工编号不存在')
            continue
        # 3.根据员工编号删除键值对
        data_dict.pop(target_delete_id)
        # 4.小提示
        print(f'员工编号{target_delete_id}数据删除成功')


'''2.定义一个功能字典'''
func_dic = {
    '1': add_emp_info,
    '2': edit_emp_salary,
    '3': check_emp_info,
    '4': check_all_emp,
    '5': delete_emp_info
}
# 1.先搭建功能框架
while True:
    print("""
        1.添加员工信息
        2.修改员工薪资
        3.查看指定员工
        4.查看所有员工
        5.删除员工数据
    """)
    # 2.获取用户输入的功能编号
    func_id = input('请输入功能的编号>>>:').strip()
    '''3.匹配功能编号'''
    if func_id in func_dic:
        '''4.根据k获取对应的v(函数名)'''
        func_name = func_dic.get(func_id)
        '''5.调用函数'''
        func_name()
    else:
        print('暂无该功能编号')
posted @   dy12138  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示