• 012.Python之函数的参数与对象


    一、函数的参数

    (一)函数参数的两大分类:

    1.形参:

    在定义函数阶段,括号内指定的参数,称之为形式参数,简称形参。形参相当于定义在函数内的变量名,用于接收外部传进来的值。

    2.实参:

    在调用函数阶段,括号内传入的值,称之为实际参数,简称实参,实参相当于变量值,用于为形参赋值的。

    3.总结:

    在函数调用时,会将实参的值绑定给形参,这种绑定关系只能在函数内使用,在函数调用完毕后,实参会与形参解除绑定,回收占用的内存空间。

    (二)函数参数的特点及具体使用

    1.位置形参

    (1)按照从左到右的顺序依次定义形参

    (2)特点:必须被传值,不可多,也不可少

    def func(x, y):
        print(x, y)
    
    func(1, 2)  # 1 2
    func(1)  # TypeError: func() missing 1 required positional argument: 'y'
    

    2.位置实参

    (1)按照从左到右的顺序依次定义实参

    (2)特点:按照位置与形参一一对应

    def func(x, y):
        print(x, y)
    
    func(1, 2)  # 1 2
    func(2, 1)  # 2 1
    

    3.关键字实参

    (1)按照key=value的形式为指定的形参传值

    (2)特点:指名道姓为某个形参传值,可以完全打乱顺序

    def func(x, y):
        print(x, y)
    
    func(1, 2)  # 1 2
    func(y=2, x=1)  # 1 2
    

    (3)注意:位置实参与关键字实参的混用

    ①不能对同一个形参重复赋值

    def func(x, y):
        print(x, y)
    
    func(1, 2, x=111)  # TypeError: func() got multiple values for argument 'x'
    

    ②关键字实参必须跟在位置实参后面

    def func(x, y):
        print(x, y)
    
    # func(1, y=2)  # 1 2  操作正确,无问题
    func(y=2, 1)  # SyntaxError: positional argument follows keyword argument
    

    4.默认参数

    (1)具有默认值的形参,指的是在定义函数阶段就已经为参数赋值

    (2)特点:在调用函数阶段可以不用为默认参数赋值

    def func(x, y=1111):
        print(x, y)
    
    func(1)  # 1 1111
    func(1,2222)  # 1 2222
    

    (3)注意:

    ①位置形参必须放在默认形参的前面

    def func(y=1, x):
        print(x, y)
    
    func(2)  # SyntaxError: non-default argument follows default argument
    

    ②默认形参的值

    默认形参的值是在函数定义阶段就被固定的,如果调用没有为默认形参传值,那么不会每次调用都重新赋值,函数的调用彼此之间应该做到没有关联,所以说默认形参的值通常应该是不可变类型。

    def func(name, names=[]):
        names.append(name)
        print(names)
    
    func("name1")  # ['name1']
    func("name2")  # ['name1', 'name2']
    func("name3")  # ['name1', 'name2', 'name3']
    
    解决办法:
    def func(name, names=None):
        if names == None:
            names = []
        names.append(name)
        print(names)
    
    func("name1")  # ['name1']
    func("name2")  # ['name2']
    func("name3")  # ['name3']
    

    5.可变长度的参数(*与**的用法)

    可变长指的是在调用函数时,传入的实参个数不固定,而实参是为形参赋值的,所以对应着也应该有新的形参格式来负责接收不固定长度的实参。

    (1)形参中带*与**

    1)*形参名:

    “ * ”会负责把溢出的位置实参存成元组,然后赋值给后面的形参名,形参名通常应该是args。

    def func(x,y,*z):
        print(x,y,z)
    
    func(1,2,3)  # 1 2 (3,)
    func(1,2,3,4)  # 1 2 (3, 4)
    func()  # 报错,TypeError: func() missing 2 required positional arguments: 'x' and 'y'
    
    2)* * 形参名:

    “* *“会负责把溢出的关键字实参存成字典,然后赋值给后面的形参名,形参名通常应该是kwargs.

    def func(x,y,**z):
        print(x,y,z)
    
    func(1,2,a=111,b=222,c=333)  # 1 2 {'a': 111, 'b': 222, 'c': 333}
    
    3)注意:*与**在形参中混用,整体规则如下:
    def func(x,y=2,*m,**n):
        print(x,y,m,n)
    
    func(1)  # 1 2 () {}
    func(1,2,3,4,5,6,7,a=1,b=2)  # 1 2 (3, 4, 5, 6, 7) {'a': 1, 'b': 2}
    
    
    def func(*args, **kwargs):
        print(args, kwargs)
    
    func(1,2,3,4,5,6,7,a=1,b=2)  # (1, 2, 3, 4, 5, 6, 7) {'a': 1, 'b': 2}
    
    # 使用*args实现一个加法运算的函数
    def add(*args):
        res = 0
        for i in args:
            res += i
        print(res)
    
    add(1,2,3,4,5)  # 15
    

    (2)实参中带*与**

    def func(x, y):
        print(x, y)
    
    1)实参中带*:

    *后跟的那个值应该是一个可以被for循环遍历的值, * 后的那个值会被分解成位置实参。

    func(*(111,222,333))  # func(111,222,333) TypeError: func() takes 2 positional arguments but 3 were given
    
    func(*(111,222))  # 111 222   func(111,222)
    
    func(*"hello")  # func("h","e","l","l","o") TypeError: func() takes 2 positional arguments but 5 were given
    
    func(*{"k1": 111, "k2": 222,})  # k1 k2  func("k1","k2")
    
    2)实参中带**:

    “* *“后跟的那个值应该是一个字典,**后面的那个值会被分解成关键字参数。

    func(**{"k1": 111, "k2": 222, })  # func(k2=222,k1=111) TypeError: func() got an unexpected keyword argument 'k1'
    
    func(**{"x": 111, "y": 222, })  # 111 222   func(y=222,x=111)
    
    func(**[("x",111),("y",222)])  # TypeError: func() argument after ** must be a mapping, not list
    

    (3)形参与实参中混用*与**

    def func(*args,**kwargs):
        print(args,kwargs)
    
    func(1,2,3,4,5,a=1,b=2,c=3)  # (1, 2, 3, 4, 5) {'a': 1, 'b': 2, 'c': 3}
    
    func((1, 2, 3, 4, 5), {'a': 1, 'b': 2, 'c': 3})  # ((1, 2, 3, 4, 5), {'a': 1, 'b': 2, 'c': 3}) {}
    
    func(*(1, 2, 3, 4, 5), **{'a': 1, 'b': 2, 'c': 3})  # func(1, 2, 3, 4, 5, a=1, b=2, c=3) (1, 2, 3, 4, 5) {'a': 1, 'b': 2, 'c': 3}
    

    示例:

    def index(x,y):
        print(x,y)
        
    def wrapper(*args,**kwargs):
        index(*args,**kwargs)
        
    # 直接调用的是wrapper,然后通过wrapper间接调用index
    wrapper(1,2,3,4,5,a=1,b=2,c=3) # TypeError: index() got an unexpected keyword argument 'a'
    #① args=(1,2,3,4,5)  kwargs={"a":1,"b":2,"c":3}
    #② index(*(1,2,3,4,5),**{"a":1,"b":2,"c":3})
    #③ index(1,2,3,4,5,a=1,b=2,c=3)  # TypeError: index() got an unexpected keyword argument 'a'
    
    wrapper(1,2)  # 1 2
    wrapper(y=2,x=1)  # 1 2
    wrapper(1,y=2)  # 1 2
    
    

    (4)总结:

    形参中带*与** 是汇总操作

    实参中带*与** 是分解操作

    6.命名关键字参数(了解)

    在*与** 之间的参数,都是命名关键字参数。

    def func(*args, y, **kwargs):
        print(args)
        print(y)
        print(kwargs)
    
    
    # func(1,2,3,a=1,b=2,c=3)  # 报错,不可以这样传值,必须给y赋值
    func(1,2,y=3,a=1,b=2,c=3)
    # (1, 2)
    # 3
    # {'a': 1, 'b': 2, 'c': 3}
    
    def func(*args, x=1, y, **kwargs):
        print(args)
        print(x,y)
        print(kwargs)
    
    func(1,2,y=3)
    # (1, 2)
    # 1 3
    # {}
    
    

    7.组合使用的顺序(了解)

    def func(x, y=111, *args, z, **kwargs):
        pass
    

    二、函数对象

    函数对象指的是函数可以被当做“数据”来处理,具体可以分为四个方面的使用:

    (一)函数可以被引用(赋值)

    def foo():
        print('from foo')
    print(foo)  # <function foo at 0x0000014D75AC63A0>
    f=foo
    f()  # from foo
    

    (二)函数可以作为容器类型的元素

    def foo():
        print('from foo')
    
    l=[foo]
    print(l)  # [<function foo at 0x000001D34A5D63A0>]
    l[0]()  # from foo
    

    (三)函数可以作为参数传入另一个函数

    def func(aaa): # aaa=函数foo的内存地址,被引用(赋值)
        print(aaa)
        # aaa()
    
    def foo():
        print('from foo')
    
    func(foo)  # <function foo at 0x0000014D77719280>
    

    (四)函数的返回值可以是一个函数

    def func(aaa): # aaa=函数foo的内存地址
        return aaa # 返回的是函数foo的内存地址
    
    def foo():
        print('from foo')
        
    res=func(foo)
    print(res)  # <function foo at 0x000001D607AF9040>
    res()  # from foo
    

    示范:

    def login():
        print('登录功能')
    
    def register():
        print('注册功能')
    
    def transfer():
        print('转账功能')
    
    def charge():
        print('充值')
    
    def withdraw():
        print('提现')
    
    func = {
        "1": ("登录",login),
        "2": ("注册",register),
        "3": ("转账",transfer),
        "4": ("充值",charge),
        "5": ("提现",withdraw)
    }
    
    while True:
        print("0 退出")
        for k,v in func.items():
            print(k,v[0])
        choice = input("请输入你的操作编号:").strip()
        if choice == "0":
            break
        if choice in func:
            func[choice][1]()
        else:
            print("输入的指令不存在")
    
  • 相关阅读:
    分享50款 Android 移动应用程序图标【上篇】
    Matter.js – 你不能错过的 2D 物理引擎
    Materialize
    Gulp.js 参考手册,自动化构建利器
    严谨而浪漫!20个来自德国网页设计
    Muzli – 所有你需要的设计灵感都在这
    FormatJS – 让你的 Web 应用程序国际化
    字体大宝库:20款免费的情人节字体
    15个优秀的 Material Design(材料设计)案例
    SpaceBase – 基于 Sass 的响应式 CSS 框架
  • 原文地址:https://www.cnblogs.com/huluhuluwa/p/13149910.html
Copyright © 2020-2023  润新知