python:工厂函数应该全部设置默认参数

python 中的工厂函数,简单理解就是:高阶函数的一种,可以返回函数的函数。

一般我们可以写出这样的工厂函数:

def func(x):
    return lambda: x

然后验证一下:

print(func(2)())
# 2

输出为2。没错,就是我们期待的结果。


然后,再来一个带循环体的(错误的示范!)

def multi(x):
    ret = []
    for ele in range(x):
        ret.append(lambda: ele)
    return ret
  • 输出验证一下:
for action in multi(5):
    print(action(),end="\t")
# 4  4  4   4   4       

这时候就出问题了。lambda 并没有记住我们所期待的ele而是记住了最后一个ele.

  • 如何解决?
  • 全部设置默认参数就好了。
    那么修改后的代码如下(正确的示范):
def multi(x):
    ret = []
    for ele in range(x):
        ret.append(lambda k=ele: k)
    return ret
  • 输出如下
for action in multi(5):
    print(action(), end="\t")
# 0  1  2   3   4   

对于之前的func()函数呢?当然也可以设置默认参数:

def func(x):
    return lambda p=x: p

通过对默认参数的设置,代码就不会依赖运行时的检查,而是在定义时就明确知道状态信息。

  • 分析:为何定义了默认参数值,就可以避免循环中出现的问题?
    multi(x)函数为例:其等价形式为:
def multi(x):
    ret = []
    for ele in range(x):
        def temp(t=ele):
            return t

        ret.append(temp)
    return ret
  • def multi(x):中,变量ele和函数temp()是同时被创建的。都是在multi(x)函数被调用时创建。
  • def temp():中的返回值t是在temp()函数被调用的时候创建。
  • 而且这两个函数总是不能同时被调用。总是需要multi(x)()这样的方式去调用。也就导致了t总是在ele创建之后被创建。
  • 所以在这样的场景下,如果不设置默认值,t返回的总是最后一个ele的值。
  • 而,如果给temp()函数设置了默认参数temp(t=ele),就强制在temp()函数被创建的时候,就创建变量t.这样刚好就达到了预期:在遍历的过程中,不断地去改变ele的值,同时t也随着ele的改变而改变。(如果不做这种默认参数的设置。对t的赋值实际上只发生了一次,也就是在temp()被调用的时候发生了一次。)

总结:

  • x,ret,ele都是在multi(x)被调用的时候创建的
  • temp()的返回值,是在temp()被调用的时候创建的
  • temp()总是在multi(x)被调用之后才调用
  • 要想让temp()得到遍历中的每次ele的值,就可以通过默认参数的方式,让temp()在遍历的过程中就得到ele的值。(这也许是目前唯一的办法

其实表述的不是很准确:python中所有对变量的赋值操作实质上都是对对象的引用的修改。
在上述行为中,也就是不断改变t的引用。t = ele = num(obj). ele每次引用不同的对象,而t总是做与ele相同的引用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值