函数基础学习之*与**在实参中的作用、命名关键字参数(冷门)、名称空间以及名称空间分类、名字的查找顺序、名称空间的作用域、局部名称空间复杂情况、global与nonlocal关键字、函数名的多种使用方式

今日内容

*与**在实参中的作用

def func(*args, **kwargs):
    print(args)
    print(kwargs)
 
'''
* 的作用:相当于是for循环拿到它后面的数据类型里面所有的值然后一次性传给函数
'''
func()  # ()  {}
func([1, 2, 3, 4, 5, 6])  # ([1, 2, 3, 4, 5, 6],) {}
l1 = [1, 2, 3, 4, 5, 6]
func(l1[0], l1[1], l1[2], l1[3], l1[4], l1[5])  # (1,2,3,4,5,6) {}
func(*l1)  # (1, 2, 3, 4, 5, 6) {}
'''
这里的*号就是将l1中的每一个数据值全部取出来,然后一次性放给了func函数,相当于变成了多个位置实参
func(1,2,3,4,5,6)
* 在实参中的作用:会将*后面的东西相当于用一个for循环取出来一次性传给函数
'''
s = 'good'
func(*s)  # ('g', 'o', 'o', 'd')   {}
'''func('g', 'o', 'o', 'd')'''
d = {'1': 'jason', '2': 58}
func(*d)  # ('1', '2') {}
'''
如果在字典中加了*号,它相当于用一个for循环一次性将字典中的k值全部取出来放入func中
func('1','2')
'''
d1 = {'username': 'jason', 'pwd': 123}
func(**d1)  # ()  {'username': 'jason', 'pwd': 123}
func(username='jason', pwd=123)  # ()  {'username': 'jason', 'pwd': 123}
'''
** 只适用于字典,将字典里的键值对把它变为关键字的参数传给函数
'''

命名关键字参数(冷门知识)

需求:在传值的时候必须按照关键字的形式传值
def func(a, b, *args):
    pass
'''
在使用这个函数的时候,必须至少传入俩个实参,如果给传多个数据的话也只能是位置实参,不能是关键字实参,因为单个*适用于关键字实参,俩个*才能传入关键字实参
'''

def func(a, b, *args, c):
    print(a, b, *args, c)
func(1, 2, 3)
'''
需要形参在传实参的时候,必须按照关键字参数才可以
在形参*args的后面
如果形参中还有**kwargs 那必须在它的前面
'''
def func(a, b, *args, c):
    print(a, b, args, c)
func(1, 2, 3, 4, 5, 6, 7)  # 报错
func(1, 2, 3, 4, 5, 6, c=666)
def func(a, b, *args, c, **kwargs):
    pass


名称空间

名称空间的介绍

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

在内存中申请一块内存空间存储jason 然后绑定变量名name

变量名name与值jason的绑定关系就会被存储到名称空间中 之后使用名字都是去名称空间中查找并锁定对应的数据值
image-20220704172800483
del name,删除的不是数据值,而是变量名以及变量名与数据值之间的绑定关系
image-20220704171946693 image-20220704172556632

名称空间分类

内置名称空间

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

存活周期:解释器运行(创建)  解释器关闭(销毁)

全局名称空间

py文件运行代码过程中产生的名字都会存入该空间

普通代码里面的变量名、分支结构里面的变量名、循环结构里面的变量名、定义函数的函数名

存活周期:py文件运行(创建)  py文件结束(销毁)

局部名称空间

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

存活周期:函数体代码运行(创建)  函数体代码结束(销毁)

名字的查找顺序

重点:查找名字之前自己在哪个名称空间
'''
三个名称空间都可以存名字,如果有个名字称三个空间里都有,找哪个
1.当前在全局名称空间时,先看全局名称空间里有没有,然后再看内置名称空间
2.当前在局部名称空间时,先看局部名称空间里有没有,然后再看全局名称空间,最后再看内置名称空间
3.名字的查找顺序默认情况下不能颠倒只能是,局部到全局再到内置
'''

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


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

名称空间的作用域

内置名称空间:在程序任意位置都可以使用(全局有效)

全局名称空间:在程序任意位置都可以使用(全局有效)

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

局部名称空间复杂情况

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)  # 3
         func3()
     func2()
 func1()

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

def func1():
    def func2():
        def func3():
			print(x)  # 报错
         func3()
     func2()
 func1()

# 嵌套关系中,找值就要从当前位置一层一层向外找
image-20220704193629563
#  冷门特殊情况,
def func1():
    x = 4
    def func2():
        x = 4
        def func3():
            print(x)  # 1
            x = 4
        func3()
    func2()
func1()
'''
函数在定义阶段的时候只检测语法不执行代码,但是在这个时候它已经确认了将来找名字先跟谁要,它在检测语法的时候检测到了func3中有X,但是在执行的时候是从上往下执行,此时x还没有定义出来,就只能报错
'''

global与nonlocal关键字

money = 999  # 存在了全局
def func():
    money = 1000  # 此时的money对于func这个局部名称空间来说是一个新的名字,存在了自己的名称空间
func()
print(money)  # 999  这里的money此时的位置是在全局名称空间里,所以找的是全局名称空间里的money

money = 999  # 存在了全局
def func():
    money = 1000
    print(money)  # 1000
func()
print(money)  # 999

'''
正常情况下 局部名称空间里面出现新的名字会在局部名称空间中存储
但是有时候需要在局部名称空间中修改全局名称空间的名字
'''
money = 999  # 存在了全局
def func():
    global money  # 在局部名称空间里用的money不再是局部名称空间里的,而是全局的,然后对money做的任何操作影响的是全局的money
    print(money)  # 1000
func()
print(money)  # 999

s = '$jason$'
def func():
    global s
    s = 'jason'
    res = s.split('$')
func()
print(s)  # jason
"""
局部修改全局名称空间中不可变类型的数据 需要使用关键字global声明
如果是可
def func1():
    x = 1
    l1 = [1,2]
    def func2():
# global x #  局部该全局
        # nonlocal x
        x = 999
        l1.append(666)
    func2()
    print(x)
    print(l1)
func1()
"""
nonlocal 在内存局部名称空间修改外层局部名称空间中的不可变类型
"""

函数名的多种使用方式

1.函数名可以被用来多次赋值(函数名与变量名使用一致)

name = func  # 让name也指向函数func指向的那块函数体代码的内存地址
name()
name1 = name
name1()  # 同样也可以调

2.函数名当做函数的实参

def index(a):
    print(a)
    a()
index(123)
name = 'jason'
index(name)
index(func) 

3.函数名还可以当做函数的返回值

def index():
    return func
res = index()
print(res)
res()

4.函数名还可以当做容器类型里面的数据值

l1 = [1,2,3,4,func]
print(l1)
l1[-1]()

作业:

def regisetr():
    username = input('请输入用户名:').strip()
    password = input('请输入密码:').strip()
    with open(r'userinfo.txt', 'r', encoding='utf8') as read_f:
        for info in read_f:
            # 循环切割索引找到名字
            data_name = info.split('|')[0]
            if username == data_name:
                print('用户已经存在')
                break
        else:
            # password = input('输入密码:').strip()
            # 将用户名与密码改为字符串格式
            user_data = '%s|%s\n' % (username, password)
            # 写入文件中
            with open(r'userinfo.txt', 'a', encoding='utf8') as write_f:
                write_f.write(user_data)
            print(f'{username}注册成功')
            return True


def login():
    username = input('请输入用户名:').strip()
    password = input('请输入密码:').strip()
    with open(r'userinfo.txt', 'r', encoding='utf8') as read_f:
        for info in read_f:
            # 对用户与密码进行切割
            data_name, data_pwd = info.split('|')
            # 判断输入是否正确
            if username == data_name and password == data_pwd.rstrip('\n'):
                print('登录成功')
                break
        else:
            print('用户名或密码有误')
def back():
    print('欢迎下次再来哦')

func_dict = {'1': regisetr,
             '2': login,
             '3': back,
             }

while True:
    print('''
        1.用户注册功能
        2.用户登录功能
        3.退出
    ''')
    funct_choice = input('请输入要执行的操作:').strip()
    if funct_choice in func_dict:
        func_name = func_dict.get(funct_choice)
        func_name()
    else:
        print('没有该功能编号')

posted @ 2022-07-04 21:46  小张不爱吃泡面  阅读(57)  评论(0编辑  收藏  举报