函数、参数

 

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

#定义格式
"""
    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)#这里实参的* 和 **为了标识传给不同类型的形参

 

#1、函数名
#打印

def Test1():
    print('test1')

print(Test1)#<function Test1 at 0x7feb2ddd4040>  函数名、地址
#赋值
T1 = Test1
T1()
#做函数的参数
def Test2(a):
    a()
    print('test2')

Test2(Test1)
#做容器类的元素
def Test3():
    print('test3')

def Test4():
    print('test4')

L1 = [Test3, Test4]
for i in L1:
    i()
#做函数返回值
def Test5(a):
    print('test5')
    return a

msg = Test5(Test4)
print(msg)#Test4函数对象
msg()#Test4执行结果


#2、闭包,内层函数对外层函数非全局变量的引用称为闭包
#例:
def Test6():
    name = 'test6'
    def Test7():
        print(name)
    Test7()
    print(Test7.__closure__)#判断函数区域是否是闭包,返回 <cell at *** 为闭包

Test6()
#如函数内声明变量为全局,则不是闭包
def Test8():
    global name #声明全局变量
    name = 'Test8'
    def Test9():
        print(name)
    Test9()
    print(Test9.__closure__)#返回None则表示不是闭包

Test8()

#*使用:闭包所在的临时名称空间不会随函数执行完毕而消失,主要用在爬虫
def make(n):
    x = []
    for i in range(n):
        x.append(lambda: print('i', i))#lambda 匿名函数,格式 lambda: 函数体
        # print(x)#x[]里存的是匿名函数对象
    return x

a, b, c = make(3)#执行make函数,把 x 分别赋给a, b, c
print(a)
print(b)
print(c)
a(), b(), c()#执行x(匿名对象) → print('i', i)


#函数的有用信息
def test():
    """
    就测试一下
    :return: T 成功, F 失败
    """

print(test.__name__)#输出函数名
print(test.__doc__)#输出函数说明

 

posted @ 2022-03-29 11:23  尐少  阅读(23)  评论(0编辑  收藏  举报