Python中函数调用和闭包

在Python中,定义函数使用def语句. 如果函数没有 return 语句,则自动 return None 。

函数参数

在Python中,他定义函数和调用函数,但如何定义函数参数和传递函数参数,则涉及到一些套路了。总的来说,Python 的函数参数主要分为以下几种:

必须参数: 

必选参数可以说是最常见的了,顾名思义,必选参数就是在调用函数的时候要传入数量一致的参数,

默认参数:

默认参数是指在定义函数的时候提供一些默认值,如果在调用函数的时候没有传递该参数,则自动使用默认值,否则使用传递时该参数的值。可以看到,默认参数使用起来也很简单,但有两点需要注意的是:默认参数要放在所有必选参数的后面默认参数应该使用不可变对象.

#默认参数:
def games(a,b=10): #这里的b,则是采用默认参数设置,如果在传递实参的过程中,不进行指定,即是默认为10
    return a+b

if __name__ == '__main__':
    print(games(10)) #输出20
    print(games(10,20)) #输出30

可变参数

在某些情况下,我们在定义函数的时候,无法预估函数应该制定多少个参数,这时我们就可以使用可变参数了,也就是,函数的参数个数是不确定的。

# 可变参数
def pr(*agrs):
    print(agrs)


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


if __name__ == '__main__':
    print(add(1, 2, 3))  # 输出6
    list1 = [1, 2, 3]
    # print(add(list1)) #报错: unsupported operand type(s) for +=: 'int' and 'list'
    print(add(*list1))  # 输出6 ,添加* 表示,将该列表以可变的位置参数,依次传入函数.
    pr(*list1)  # 输出为 元组格式: (1, 2, 3) ,在可变为位置参数中,函数接收后输出的默认格式为元组

关键字参数;

可变参数允许你将不定数量的参数传递给函数,而关键字参数则允许你将不定长度的键值对,作为参数传递给一个函数:.

def add(**kwargs):
    return kwargs


if __name__ == '__main__':
    print(add(a=1, b=2, c=3))
    # 输出 {'a': 1, 'b': 2, 'c': 3} 为字典数据类型
    dict1 = {'a': 10, 'b': 20, 'c': 30}
    # print(add(dict1)) #报错: add() takes 0 positional arguments but 1 was given
    print(add(**dict1)) #输出:{'a': 10, 'b': 20, 'c': 30}

在代码中,kwargs就是一个关键字参数,它前面有两个*号,kwargs可以接受不定长度的键值对,在函数的内部,他会表示成为一个dict字典.,和可变的参数类似,我们也可以使用**kwargs的形式来调用函数: 需要注意函数调用的时候,的实参前面也需要有两个*号

参数组合:

在实际使用中,我们通常使用参数组合,但对于,这些参数的使用时有顺序的,

依次是必选参数,默认参数,可变参数和关键字参数.在调用函数的时候,Python中会自动按照按参数的位置和参数名把对应的参数传递进去:*args 表示可变参数, **kwargs 表示关键字参数。

参数组合在使用的时候是有顺序的,依次是必选参数、默认参数、可变参数和关键字参数。

*args 和 **kwargs 是 Python 的惯用写法

#参数组合
def func(x,y,z=0,*args,**kwargs):
    print('x=',x)
    print('y=',y)
    print('z=',z)
    print('args=',args)
    print('kwargs=',kwargs)
if __name__ == '__main__':
    func(1,2,3,4) #注意实参和形参的对应位置,这样输出结果中kwargs为空
    func(1,2,3,4,5,6,a=9) # 输出x= 1,y= 2,z= 3,args= (4, 5, 6),kwargs= {'a': 9}
#注意实参的录入方式
def func1(a,b,*,c,d): #这种方式需要注意参数的传递,在*之后就只能采用关键字参数传递
    print('a=',a)
    print('b=', b)
    print('c=',c)
    print('d=',d)
if __name__ == '__main__':
#注意实参的录入方式
    func1(a=10,b=20,c=30,d=40)
    func1(10,20,c=30,d=40)
    func1(10,20,30,d=40) #报错:func1() takes 2 positional arguments but 3 positional arguments (and 1 keyword-only argument) were given

注意: 在函数的调用过程中,如果是不可变对象,在函数体内的修改不会影响实参的值.如果是可变的对象,则是在函数内部的修改会影响到实参的值.

 

高阶函数

高阶函数:一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),满足其一则为高阶函数。

高阶函数-mapfilterreduce

  这三个函数均为高阶函数,其也为Python内置的函数。接下来我们看一下这三个函数的用法以及其内部原理是怎样的:

map:

函数的使用形式: map(function ,sequence)解释:对 sequence 中的 item 依次执行 function(item),并将结果组成一个 List 返回,也就是:[function(item1), function(item2), function(item3), ...] [function(item1), function(item2), function(item3), ...]map函数接收的是两个参数,一个函数,一个序列,其功能是将序列中的值处理再依次返回至列表内。其返回值为一个迭代器对象--》例如:<map object at 0x00000214EEF40BA8>。其用法如图:

 

#高阶函数map
num = [1,2,3,4,5]
def square(x):
    return x*2
#map函数模拟:
def maps(func,iter):
    num1=[]
    # print(iter)
    for i in iter:
        ret=func(i) #调用传递的函数处理,iter中元素
        # print(ret)
        num1.append(ret)
    return num1.__iter__()# 将返回的num1转换为迭代器对象,

#调用构造函数
print(list(maps(square,num))) #输出: [2, 4, 6, 8, 10]
#调用map函数
print(list(map(square,num)))#输出: [2, 4, 6, 8, 10]

reduce函数的使用:

reduce函数也是一个参数为函数,一个为可迭代对象的高阶函数,其返回值为一个值而不是迭代器对象,故其常用与叠加、叠乘等,图示例如下:

 

 

# reduce函数不是内置函数,而是在模块functools中的函数,故需要导入
from functools import reduce

num = [1, 2, 3, 4, 5, 6]


# reduce函数机制
def reduces_test(func, array, ini=None):  # ini作为基数
    if ini == None:
        retu = array.pop(0)
    else:
        retu = ini
    for x in array:
        retu = func(retu, x)
    return retu


print(reduces_test(lambda x, y: x * y, num, 1)) #720

 

闭包

在python中,函数也是一个对象, 因此,我们在定义函数时,可以再嵌套定义一个函数,并将该嵌套函数返回,

from math import pow

# pow 函数,math类库中自带的求次方的方法
# 定义函数:
def make_pow(n):
    def inner_func(x):
        return pow(n, x)  # 返回该函数的计算结果

    return inner_func  # 外部函数调用,返回内部函数的名称


print(make_pow(2)(3))  # 这里传递两个参数,需要传递外部和内部函数需要的参数

在上面的代码中函数make_pow里面有定义了一个函数,inner_func,然后将该函数进行返回,因此可以使用make_pow来生产另一个函数. 我们还注意到,内部函数 inner_func 引用了外部函数 make_pow 的自由变量 n ,这也就意味着,当函数 make_pow 的生命周期结束之后, n 这个变量依然会保存在 inner_func中,它被 inner_func 所引用。像上面这种情况,一个函数返回一个内部函数,该内部函数引用了外部函数的相关参数和变量,我们把这种返回的内部函数称为闭包.

闭包的作用:       闭包最大的特点就是引用了自由变量,即是生产的闭包的环境已经释放,当闭包任然存在,闭包在运行时可以有多个实例 ,即是传入的参数相同.利用闭包,我们还可以实现模拟类:

注意; 闭包是携带自由变量的函数,即创建闭包的外部函数的声明周期结束了,闭包所引用的自由变量会任然存在. 

闭包在运行中可以有对个实例对象,尽量不要在闭包中引用循环变量,或者后续会发生变化的变量,这会导致值被覆盖的可能,.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴爃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值