ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

函数之重要参数、名称空间及作用域

2022-07-04 22:06:25  阅读:137  来源: 互联网

标签:函数 作用域 空间 参数 名称 func print def name


函数之重要参数、名称空间及作用域

一、重要参数

1、*与**在形参中的作用

1.*在形参中接收多余的位置实参,并组织成元组的形式返回数据值,且位置实参可以是任意的数据类型。
2.**在形参中接收多余的关键字实参,并以字典的形式返回数据值。
3.*与**若只在形参中出现,都是接收多余的实参,若没有多余的参数不会报错。两者同时出现时,*接收多余的位置实参,以元组的形式返回数据值;**接收多余的关键字实参,以字典的形式返回数据值。两者的结合即接收任意类型的多个参数。
# 1.*在形参中接收多余的位置实参
def func1(a, *args):
    print(a, args)
func1(2, 4, 5, 6, [1, 2, 3, 4, 5, 6])  # 2 (4, 5, 6, [1, 2, 3, 4, 5, 6])
func1(2, {'name': 'jason'})  # 2 ({'name': 'jason'},)
func1(2, True)  # 2 (True,)

# 2.**在形参中接收多余的关键字实参
def func2(a, **kwargs):
    print(a, kwargs)
func2(2, name='jason', age=18)  # 2 {'name': 'jason', 'age': 18}

# 3.两者同时出现
def func3(*args, **kwargs):
    print(args, kwargs)
func3(1, 2, 3, 4, 5, 6, name='jason', age=18, hobby='read')
# (1, 2, 3, 4, 5, 6) {'name': 'jason', 'age': 18, 'hobby': 'read'}

2、*与**在实参中的作用

1.*在实参中将*后面的变量名或数据值依次全部取出(相当于for循环依次取出),然后一次性传给函数,变成多个位置参数以元组的形式传给函数。
2.**在实参中将字典中的键值对变成关键字形式的参数传给函数,只针对字典。
def func1(*args, **kwargs):
    print(args, kwargs)

# 1.*在实参中
l1 = [1, 2, 3, 4, 5, 6]
func1(*l1)  # (1, 2, 3, 4, 5, 6) {}
s = 'world'
func1(*s)  # ('w', 'o', 'r', 'l', 'd') {}
d = {'1': 'jason', '2': 22}
# 字典只有键参与
func1(*d)  # ('1', '2') {}

# 2.**在实参中
d1 = {'name': 'jason', 'pwd': 123}
# 只有关键字参数可以
func1(**d1)  # () {'name': 'jason', 'pwd': 123}

3、命名关键字参数

1.若想*args后面接着跟形参,则在实参中,*args后面的位置参数必须要按照关键字参数的形式传值。
2.若想*args和**kwargs后面接着跟形参,那么两者之间至少要隔一个形参,且这个形参必须以关键字的形式传值。
# 可按照位置传值也可按照关键字传值
def func(a, b, *args):
    print(a, b, args)
func(1, 2)  # 1 2 ()
func(a=1, b=2)  # 1 2 ()
func(1, b=2)  # 1 2 ()

# 1.c必须按照关键字形式传值
def func1(a, b, *args, c):
    print(a, b, args, c)
func1(1, 2, 3, 4, 5, 6) # 报错

# 1.*args后面接着跟形参
def func2(a, b, *args, c):
    print(a, b, args, c)
# c必须以关键字参数传值
func2(1, 2, 3, 4, 5, c=6)   # 1 2 (3, 4, 5) 6


# 2.*args和**kwargs中间以C关键字传值
def func3(a, b, *args, **kwargs, c):
    print(a, b, args, kwargs, c)
func3(1, 2, 3, 4, 5, c=6)   # 报错

# 2.*args和**kwargs中间以C关键字传值
def func4(a, b, *args, c, **kwargs):
    print(a, b, args, c, kwargs)
# *args和**kwargs连用时关键字参数传值必须放中间
func4(1, 2, 3, 4, 5, c=6, name='jason', age=18)
# 1 2 (3, 4, 5) 6 {'name': 'jason', 'age': 18}

二、名称空间

名称空间存放变量名和变量名与数据值绑定的关系的地方。

name = 'jason'

del name

1、内置名称空间

python解释器运行就会立即创建的空间,可直接使用的方法(名字)都在内置名称空间。eg:len()、print()、input()等。

len()
print()
input()

2、全局名称空间

python文件运行代码的过程中产生的变量名(名字)都会存在在全局名称空间。普通代码中的变量名、分支结构中的变量名、循环结构中的变量名、定义函数的变量名、定义累的类名。

a = 1	# a全局内
if 1 == 1:	
    b = 2	# b全局内

for i in range(6):	# i全局内
    pass

def func():	 # func全局内
    name = 'jason'	# name不在全局内,因为只检测语法不执行代码
    print(name)

3、局部名称空间

函数体代码运行过程中产生新的变量名(名字)都会存放在局部名称空间。

def func():	 # func全局内
    name = 'jason'	# name局部名称空间
    def func1():	# func1局部名称空间
        age = 18	# age局部名称空间

4、名称空间的存活周期

1.内置名称空间

开始:python解释器启动创建内置名称空间

结束:python解释器关闭销毁内置名称空间

2.全局名称空间

开始:python文件运行创建全局名称空间

结束:python文件运行结束销毁全局名称空间

3.局部名称空间

开始:函数体代码运行创建局部名称空间

结束:函数体代码运行结束销毁局部名称空间

5、名称空间的查找顺序(重要)

先看自己在哪个在名称空间。若起始位置是在全局名称空间,先查找全局名称空间,没有再去内置名称空间查找,内置若没有则会报错。

若起始位置在局部名称空间,先查找局部名称空间,没有去全局名称空间,再没有去内置名称空间,内置若没有则会报错。

len = '我是全局名称空间的len'
def func():
    len = '我是局部名称空间里的len'
func()
print(len)  # 我是全局名称空间的len

len = '我是全局名称空间的len'
def func():
    len = '我是局部名称空间里的len'
    print(len)  # 我是局部名称空间的len
func()

def func():
    len = '我是局部名称空间里的len'
func()
print(len)  # <built-in function len>

def func():
    len = '我是局部名称空间里的len'
    print(len)  
func()  # 我是局部名称空间里的len

三、作用域

1、内置名称空间

在程序任意位置都可以使用名字(全局有效)

2、全局名称空间

在程序任意位置都可以使用名字(全局有效)

3、局部空间名称

在各自的局部空间可以使用名字(局部有效)

4、局部名称空间复杂情况

1.局部名称空间在默认情况下彼此之间互不干扰。

# 局部名称空间默认情况下彼此互不干扰
def func1():
    name = 'jason'
    print(age)

def func2():
    age = 18
    print(name)

func1()
func2()

2.嵌套,由内到外的查找。

x = 1
def func1():
    x = 2
    def func2():
        x = 3
        def func3():
            x = 4
            print(x)    # 4
        func3()
    func2()
func1()

特殊情况:不能在没定义前使用,函数在定义阶段名字的查找顺序已经不能改变
x = 1
def func1():
    x = 2
    def func2():
        x = 3
        def func3():
            print(x)  # 报错,提示x在在定义前使用了
            x = 4
        func3()
    func2()
func1()

# 在哪里就看哪里的位置
x = 10
def func1():
    x = 9
    print(x)
x = 100
func1()  # 9

x = 10
def func2():
    print(x)
x = 100
func2()  # 100

image

image

四、global与nonlocal关键字

global:局部修改全局名称空间中的不可变数据类型(声明局部名称空间中的变量名(名字)操作的是全局名称空间的变量名)。如果是可变类型不需要关键字声明。

# 不可变数据类型
x = 999
def func1():
    global x  # 声明局部名称空间中的x操作的是全局名称空间的x
    x = 1000    # 将全局中绑定定的999关系断开重新绑定1000
    print(x)
func1() # 1000

s = '$jason$'
def func():
    global s
    s = 'jason'
func()
print(s)    # jason

# 可变数据类型
l1 = [1, 2, 3, 4, 5]
def func():
    l1 = [1, 2, 3]
    l1.append(666)
    print(l1)
l1.append(777)
func()  # [1, 2, 3, 666]
print(l1)   # [1, 2, 3, 4, 5, 777]

l1 = [1, 2, 3, 4, 5]
def func():
    l1.append(666)
    print(l1)
l1.append(777)
func()  # [1, 2, 3, 4, 5, 777, 666]
print(l1)   # [1, 2, 3, 4, 5, 777, 666]

nonlocal:在内层局部名称空间修改外层局部名称空间中的不可变数据类型。如果是可变类型不要关键字声明。

# 不可变数据类型,声明关键字
def func():
    x = 1
    def func2():
        nonlocal x
        x = 22
    func2()
    print(x)    # 22
func()

# 可变数据类型,无需声明
def func():
    x = 1
    l1 = [1, 2, 3]
    def func2():
        l1.append(888)
    func2()
    print(l1)   # [1, 2, 3, 888]
func()

五、函数名的多种用法

1、函数名可以绑定多个新的名字,被用来赋值(函数名与变量名使用方法一致)

2、函数名可以当作函数的实参

3、函数名可以当作函数的返回值

4、函数名可以当作容器的类型里面的数据值

# 1.函数名可以被用来多次赋值
def func():
    print('hello')
    
name = func
print(name)  # <function func at 0x0000018D6D380840>
name1 = name
name1()  # hello


# 2.函数名可以当做函数的实参
def func():
    print('hello')
    
def index(a):
    print(a)    # <function func at 0x000001AADED90840>
    a()
# index(123)
# name = 'jason'
# index(name)
index(func)  # (a = func)  hello


# 3.函数名还可以当作函数的返回值
def index():
    return func

res = index()
print(res)  # <function func at 0x000001AC19370840>
res()   # hello


# 4.函数名还可以当做容器类型里面的数据值
def func():
    print('hello')
    
l1 = [1, 2, 3,4, 5, 6, func]
print(l1)   # [1, 2, 3, 4, 5, 6, <function func at 0x000001A064580840>]
l1[-1]()    # [func()] hello

补充

def register():
    print('注册功能')

def login():
    print('登录功能')

def check_account():
    print('查看账户余额')
    
# 提前构造功能字典
func_dict = {'1': register,
             '2': login,
             '3': check_account
             }

while True:
    print("""
    1.注册功能
    2.登录功能
    3.查看余额
    """)
    choice = input('>>>:').strip()
    if choice in func_dict:
        func_name = func_dict.get(choice)
        func_name()
    else:
        print('没有该功能编号')

作业

def add():
    number_dict = {}
    number = input('请输入用户编号:').strip()
    if number in number_dict:
        print('该员工已存在')
    else:
        user_info = {}
        name = input('请输入要添加的员工姓名:').strip()
        age = input('请输入员工年龄:').strip()
        post = input('请输入员工岗位:').strip()
        salary = input('请输入员工薪资:').strip()
        user_info['name'] = name
        user_info['age'] = age
        user_info['post'] = post
        user_info['salary'] = salary
        number_dict[number] = user_info
        print(f'员工编号{number}添加成功')
        print(number_dict)


def update():
    number_dict = {}
    number = input('请输入员工编号:').strip()
    if number not in number_dict:
        print('该员工不存在')
    else:
        user_info = number_dict[number]
        new_salary = input('请输入修改后的薪资:').strip()
        user_info['salary'] = new_salary
        number_dict[number] = user_info
        print('薪资修改成功')
        print(number_dict)



def check_one():
    pass


def check_all():
    pass


def delete():
    pass


func_dict = {
    '1': add,
    '2': update,
    '3': check_one,
    '4': check_all,
    '5': delete
}

while True:
    print('''
    1.添加员工信息
    2.修改员工薪资
    3.查看指定员工
    4.删除员工数据
    ''')
    choice = input('请输入你的指令:').strip()
    if choice in func_dict:
        func_choice = func_dict.get(choice)
        func_choice()
    else:
        print('无法执行该指令')

没有写出来

标签:函数,作用域,空间,参数,名称,func,print,def,name
来源: https://www.cnblogs.com/lovejimin/p/16444558.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有