函数、参数


#为解决可读性差,重复代码

#定义格式
"""
    def 函数名(形参):
        函数体
        return 返回值/结束函数,多个值以元组形式返回

#执行
函数名(实参)#需要和函数形参数量一致
"""


#1、示例
def my_len(OBJ):
    count = 0
    for i in OBJ:
        count += 1
    return count

a = [1, 2, 3]
print(my_len(a))
#2、关键字参数 直接给形参赋值, 但位置传参一定在最后
def Test1(a, b, c):
    print(a, b, c)
    return a, b
#Test1(1, 2, b = 3) #报错,不能给中间形参关键字传参
Test1(1, c = 2, b = 3) #可以,最后的关键字参数顺序可变

#3、默认参数
def Test2(a, b, c = 110): #1、默认参数必须放在形参最后;2、不传取默认,传值覆盖默认值
    print(a, b, c)
Test2(1, 2) #1 2 110
Test2(1, 2, 3) #1 2 3

#!!!函数的默认参数是可变数据类型时,无论使用多少次默认参数,都是同一个(共用)
def L(a, list = []):
    list.append(a)
    return list

list1 = L(10)#没传使用默认参数
list2 = L(123, [])#传空列表后,默认参数被覆盖
list3 = L('a')#没传仍然使用默认参数,当前默认参数为[10]

print(list1, list2, list3)#[10, 'a'] [123] [10, 'a']


#4、动态参数,数量不确定或方便扩展,用 *args  **kwargs(args和kwargs是约定俗成的写法,不是必须用这两个变量名)
def Test3(*args, **kwargs):
    print("args", args)#(1, 2, 3)#接收位置参数,元组类型
    print("kwargs", kwargs)#{'x': 4, 'y': 5}#接收关键字参数,字典类型

Test3(1, 2, 3, x=4, y=5)

#!!!动态参数*args接收位置参数时,必须放在其他参数位置后,关键字参数之前;
"""!!!同理,**kwargs 也必须放在其他关键字参数之后,所以传参顺序是 (位置参数, *args, 关键字参数, **kwargs)"""
# def Test4(a, b, c='test',*args):
def Test4(a, b, *args, c='test'):
    print(a, b, args, c)

Test4(1, 2, 4, c='Test')#1 2 (4,) Test

#
def Test5(*args):
    sum = 0
    for i in args:
        sum += i
    return sum

print(Test5(1, 2, 3, 5, 8))#19
#在函数的定义中, * 是聚合对象,所以如上 *args 接收多个参数
#在函数执行时, * 是打散可迭代对象,如下:
def Test6(*args, **kwargs):
    #接收位置参数,元组类型
    print("args", args)#args (1, 2, 3, 4, 5, 'x')
    print("*args", *args)#*args 1 2 3 4 5 x
    #接收关键字参数,字典类型
    print("kwargs", kwargs)#kwargs {'y': 5, 'z': 6}
    # print("**kwargs", **kwargs)#报错,print()函数不支持关键字参数

a = [1, 2, 3]
b = [4, 5]
c = {'x': 4}
d = {'y': 5}
e = {'z': 6}
Test6(*a, *b, *c, **d, **e)#这里实参的* 和 **为了标识传给不同类型的形参