函数-2

目录

函数的参数

  • 参数简介
  • 位置参数
  • 关键字参数
  • 默认值参数
  • 可变长参数
  • 命名关键字参数

名称空间

作用域

global 与 nonlocal 关键字

函数名的多种使用方式

函数的参数

  • 参数的简介

    函数的参数分为形参和实参两大类

    形参:在定义函数时,所需定义的值。本质就是变量名,用来接收外部传来的值。

    实参:在调用函数时,所需输入的值。本质就是数据值(可以是常量,变量,表达式或三者的结合)

    在函数调用阶段形参会临时与实参进行绑定 函数运行结束立刻解除

  • 位置参数

    按照顺序定义参数,从左往右依此定义形参和实参。

    形参和实参的位置是一一对应的

  • 关键字参数

    在调用函数时,实参可以是kv键值对,又称为关键词参数。这样的实参可以不按照顺序来定义实参,仍能定义形参。

    实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

  • 默认值参数

    默认值参数就是在函数定义阶段,( ) 中以 ... = ... 的形式填写的形参

    1.在函数定义阶段就给形参绑定值 后续调用阶段就可以不传
    2.调用阶段不传值就使用默认的 传了就用传了的
    3.需要遵循前面总结的规律(简单的在左边 复杂的在右边)

  • 可变长参数

    可变长形参与实参可以随意传值

    在形参中 * 的作用:

    接受多余的位置参数组合成元组的形式赋值给* 后面的变量名

    在形参中 ** 的作用
    接收多余的关键字参数并组织成字典的形式赋值给 ** 后面的变量名

    实参中的*会获取可迭代对象的 key(索引/键值)

    由于获取的是可迭代对象的 key,所以函数的形参可以为位置参数或可变参数

1. 形参为位置参数:
def foo(n1, n2, n3, n4, n5):
        return n1, n2, n3, n4, n5
    d = {'n1': 5, 'n2': 6, 'n3': 7, 'n4': 8, 'n5': 9}
    print(foo(*d))    #  ('n1', 'n2', 'n3', 'n4', 'n5')
2. 形参为可变参数:
    def fu(*n):
        print(n)
    d = {'n1': 5, 'n2': 6, 'n3': 7, 'n4': 8, 'n5': 9}
    print(fu(*d))    #  ('n1', 'n2', 'n3', 'n4', 'n5')

"""将实参中的字典对象换成列表、元组或者字符串对象,都是可以的"""

实参中的**会获取可迭代映射的 value
由于获取的是可迭代对象的 value,所以函数的形参只能为关键字参数,即参数的个数和名称都是固定的

def foo(n1, n2, n3, n4, n5):
        return n1, n2, n3, n4, n5
    d = {'n1': 5, 'n2': 6, 'n3': 7, 'n5': 8, 'n4': 9}
    print(foo(**d))    # (5, 6, 7, 9, 8)

如果我们要调用的函数不是关键字形参,或者关键字形参与传入的实参无法一一对应,那就会报错

  • 命名关键字参数
 def func(a,b,*args):
     pass
 func(1,2)
 func(a=1,b=2)
 func(1,b=222)
'''需要形参在传实参的时候 必须按照关键字参数才可以'''
 在形参*args的后面
 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)
# 如果形参中还有**kwargs 那必须在它的前面
def func(a,b,*args,c,**kwargs):
    pass
func(1,2,3,4,5,6,c=123,name='jason')

名称空间

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

名称空间分类 各个名称空间作用 作用域 存活周期
内置名称空间 python解释器运行就会立刻创建的空间,写代码过程中可以直接使用的名字都在该空间中 在程序任意位置都可以使用(全局有效) 解释器运行(创建),解释器关闭(销毁)
全局名称空间 py文件运行代码过程中产生的名字都会存入该空间 在程序任意位置都可以使用(全局有效) py文件运行(创建) , py文件结束(销毁)
局部名称空间 函数体代码运行过程中产生的名字都会存入该空间 在各自的局部空间可以使用(局部有效) 函数体代码运行(创建) 函数体代码结束(销毁

名称的查找顺序

  1. 当前在全局名称空间的时候,查找循序是先是全局空间再是内置空间

  2. 当前在局部名称空间时,先是局部名称空间,再是全局名称空间,最后是内置名称空间

    名字的顺序不能颠倒,只能是局部——全局——内置

    查找名字前,要先确定在哪个内存空间

  • 局部名称空间的复杂程度
  1. 各自局部名称空间默认的情况下不能彼此共享名字
def func1():
    name = 'jason'
    print(age)

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

func1()
func2()
# 直接报错
  1. 在嵌套模式:
# x = 1
#
#
# def func1():
#     x = 2
#     def func2():
#         x = 3
#         def func3():
#             # x = 4
				 # print(x)
#         func3()
#     func2()
# func1()



name = 'jason'
def func():
    print(name)
    name = 'jasonNB'
func()
函数在定义阶段其实名字的查找顺序就已经固定死了

global与nonlocal关键字

# money = 999

# def func():
#     global money  # 声明 局部名称空间中的money操作的是全局的money
#     money = 1000
#     print(money)   # 1000

正常情况下 局部名称空间里面出现新的名字会在局部名称空间中存储
但是有时候需要在局部名称空间中修改全局名称空间的名字



# l1 = [1, 2, 3, 4, 5]
# s = '$jason$'

# def func():
    # global s
    # s = 'jason'
    # res = s.strip('$')
    # l1.append(113123)
    # l1.append(666)

# func()  # jason
# print(l1) # [1, 2, 3, 4, 5, 113123, 666]

局部修改全局名称空间中不可变类型的数据 需要使用关键字global声明
如果是可变类型 则无需关键字声明


def func1():
    x = 1
    l1 = [1,2]
    def func2():
        # nonlocal x
        x = 999
        l1.append(666)
    func2()
    print(x)
    print(l1)
func1()

nonlocal 在内存局部名称空间修改外层局部名称空间中的不可变类型

函数名的多种使用方式

  • 1.函数名也可以被用来多次赋值(函数名与变量名使用一致)
 def func():
     print('from func')
 name = func
 name()
 name1 = name
 name1()
  • 2.函数名还可以当做函数的实参
 def func():
     print('from func')
 def index(a):
     print(a)
     a()
 index(123)
 name = 'jason'
 index(name)
 index(func)
    1. 函数名还可以当做函数的返回值
 def func():
     print('from func')
 def index():
     return func
 res = index()
 print(res)
 res()
  • 4.函数名还可以当做容器类型里面的数据值
def func():
     print('from func')
 l1 = [1,2,3,4,func]
 print(l1)
 l1[-1]()
  • 5.构造代码流程
def register():
    print('注册功能')


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


def check_account():
    print('查看账户余额')


def withdraw():
    print('体现功能')


def shopping():
    print('购物功能')


def transfer():
    print('转账功能')


# 提前构造功能字典
func_dict = {'1': register,
             '2': login,
             '3': check_account,
             '4': withdraw,
             '5': shopping,
             '6': transfer
             }

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

今日作业

用文件实现不了全部功能

# 编写员工管理系统
# 1.添加员工信息
# 2.修改员工薪资
# 3.查看指定员工
# 4.查看所有员工
# 5.删除员工数据
# 提示:用户数据有编号、姓名、年龄、岗位、薪资
# 储存到  userinfo.txt
# 数据格式采用字典:思考如何精准定位具体数据>>>:用户编号的作用


def register():
    """
    用于添加员工的基本信息
    编号、姓名、年龄、岗位、薪资
    然后存储到文件userinfo。txt中
    :return:
    """
    # 1.获取员工的编号
    uid = input('请输入员工的编号:').strip()
    # 2.判断当前用户是否存在
    with open(r' userinfo.txt', 'r', encoding='utf8') as f:
        for line in f:
            real_uid = line.split('|')[0]  # 拆分出员工编号
            if uid == real_uid:  # 进行比对
                print('该员工编号已存在')
                break
        else:
            name = input('请输入员工姓名:').strip()
            age = input('请输入员工年龄:').strip()
            post = input('请输入该员工的岗位:').strip()
            pay = input('请输入该员工的薪资:').strip()
            # 构造员工信息数据
            user_data = '%s|%s|%s|%s|%s\n' % (uid, name, age, post, pay)
            # 写入文件
            with open(r' userinfo.txt', 'a', encoding='utf8') as f:
                f.write(user_data)
                print('填写完毕')
                return True


def salary():
    """
    读取文件修改选定员工的薪资并保持
    :return:
    """
    import os
    uid = input('请输入员工的职工号:').strip()
    # 读取文件内容
    with open(r' userinfo.txt', 'rt', encoding='utf8') as f,\
        open(' userinfo.txt.swap','wt',encoding='utf8') as wrife_f:
        for line in f:
            real_uid = line.split('|')[0]     # 拆分员工编号

            if real_uid == uid:               # 对比员工编号
                money = input('请输入更改的薪资:').strip()

                pay = line.split('|')[4]

                new_line = line.replace(pay,money)    # 修改薪资

                wrife_f.write(new_line)        # 修改信息


    os.remove(' userinfo.txt')
    os.rename(' userinfo.txt.swap', ' userinfo.txt')

def view():
    """
    读取文件内容
    查看指定员工信息
    :return:
    """
    uid = input('请输入员工的职工号:').strip()
    # 读取文件内容
    with open(r' userinfo.txt', 'rt', encoding='utf8') as f:
        for line in f:
            real_uid = line.split('|')[0]
            if real_uid == uid:
                print(line)
            else:
                print('该职工号不存在')
                return True


def all_view():
    """
    读取文件内容
    查找所有员工信息
    :return:
    """
    with open(r' userinfo.txt', 'rt', encoding='utf8') as f:
        print(f.read())

        return True


def delete():
    """
    查看文件内容
    读取该职工数据
    删除该员工信息
    :return:
    """
    uid = input('请输入员工的职工号:').strip()
    # 读取文件内容
    with open(r' userinfo.txt', 'rt', encoding='utf8') as f:
        for line in f:
            real_uid = line.split('|')[0]
            if real_uid == uid:
                del line
                print('该职工已删除')


            else:
                print('未找到该职工编号')
                return True


dict = {
    '1': register,
    '2': salary,
    '3': view,
    '4': all_view,
    '5': delete
}

while True:
    print("""
        1.添加员工信息
        2.修改员工薪资
        3.查看指定员工
        4.查看所有员工
        5.删除员工数据
    """)
    choice = input('请输入所需实现的功能:').strip()
    if choice in dict:
        func = dict.get(choice)
        func()
    else:
        print('没有该功能')
posted @ 2022-07-04 21:16  Nirvana*  阅读(34)  评论(0)    收藏  举报