当前位置:网站首页>函数基础学习02

函数基础学习02

2022-07-05 03:33:00 zxr1002

昨日内容回顾

函数:

​ 可以看作是一个工具,定义好然后可以重复的使用

函数的语法结构:

def 函数名():
	'''函数的注释'''
    函数体代码
    return 返回值

函数定义与调用:

​ 定义的时候必须使用关键字def

​ 函数的定义必须要在函数的调用前面

​ 函数在定义阶段只是会检测循环体代码的语法是否有误

函数的分类:

​ 内置函数:python解释器自己提前定义好的函数,可以直接拿来使用,它与内置方法会有所不同,后者需要跟在具体的数据类型后面使用

​ 自定义函数:

​ 空函数:没有参数,没有函数代码块,可以用于项目搭建的前期使用

​ 无参函数:没有参数,无需传值可以直接拿来使用

​ 有参函数:在调用的时候需要传入参数才可以使用

函数的返回值:

​ 函数在执行以后返回的结果,可以有也可以没有。

​ 没有return,返回的是None

​ 有return,没有返沪的值,返回也是None

​ 有return,有返回值,返回的就是值,或者返回的是变量名的时候,那么结果返回的就是它对应的绑定的值。

​ 当函数遇到return的时候,就会结束函数代码的执行,就相当于循环遇到了break

函数的参数:

​ 形式参数:在定义阶段函数括号内从左向右依次输入的变量名

​ 实际参数:在调用阶段函数括号内从左向右依次输入的数据值或者变量名

​ 俩者之间的关系,就好比是变量名与数据值,他们俩只有在函数调用的阶段会临时绑定,函数执行结束以后就会解除关系。动态绑定动态解除

函数的位置参数:

​ 位置形参:在定义阶段输入的参数

​ 位置实参:在调用阶段输入的参数

​ 位置形参的个数要与位置实参的个数要一致,不能多也不能少

函数的关键字参数:

​ 在调用阶段传入的参数,形如什么=什么的这种形式

​ 在同一时间调用函数的时候,一个形参不能同时传入多个数据

​ 传参的方式以数据的简单到复杂传入

函数的默认值参数:

​ 在函数的定义阶段,函数传入的参数形如什么=什么

​ 在函数定义阶段直接设置形参的初始值,后期在调用阶段的时候可以重新设置值传入,也可以不传值进去,不传的话默认就是原来的那个值

函数的可变长参数:

​ 可变长形参:可以传入多个值,打破了形参与实参个数的限制

*args----位置形参,**kwargs----关键字形参

今日内容

*与**在实参中的作用

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

func(1, 2, 3, 4, 5, 6, c=123, name='jason')
d1 = {'username': 'jason', 'pwd': 123}
func(**d1)  # ()  {'username': 'jason', 'pwd': 123}
func(username='jason', pwd=123)  # ()  {'username': 'jason', 'pwd': 123}
'''
** 只适用于字典,将字典里的键值对把它变为关键字的参数传给函数
'''

名称空间

名称空间的介绍

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

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

​ 变量名name与值jason的绑定关系就会被存储到名称空间中 之后使用名字都是去名称空间中查找并锁定对应的数据值

image-20220704172800483

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

image-20220704171946693image-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('没有该功能编号')

原网站

版权声明
本文为[zxr1002]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/zxr1002/p/16444568.html