56、Python之函数高级:学了不会用?高阶函数在功能迭代中的实践

引言

前面我们介绍了Python中的高阶函数的特性,对有些新手来说,难度是有点,但也不至于学不会。尴尬的地方在于,这些个看似高级的特性,似乎除了炫技没啥用啊。甚至,有些用了Python挺长时间的老手,也基本没有使用过这些特性。如果只是屠龙技,似乎不学也罢。

针对这些困惑,笔者打算结合技术特性、项目迭代、复用性、扩展性等的综合分析,来看下高阶函数特性的价值,从而真正做到学以致用。

本文的主要内容有:

1、牛逼的技术及如何学习

2、功能迭代的应对方案

3、高阶函数在功能迭代中的实践

牛逼的技术及如何学习

在我看来,一门技术不是因为其多么的“高大上”,所以牛逼;而是因为它可以被广泛地应用起来,才是真的牛逼。

一门技术如果长久的存在,显然有其存在的必然性。如果真的是屠龙技,估计必然不会长久的存在下去。

那么,为什么在有些人眼里很牛逼的技术特性,而在另一些人眼中,会显得很鸡肋,比如“费了老大力气才学会,可是实际工作中并没有什么卵用”。

在我看来,一门编程技术中的所有功能、特性,可以分为两种:

1、用于从0到1,快速创造一个新功能的特性。

2、用于从1到100,可以良好的扩展,从而有效支撑需求迭代的特性。

说到高阶函数的特性,虽然我们讲了很多,但是,它实际上属于第2种技术特性。如果你是新手,觉得学来无用,我是可以理解的。但是,如果你是个编程老手,觉得学来无用,其实,我是不太能理解的。要么,是你经历的项目都比较简单,用不着进行迭代,一锤子买卖;要么,就是你每次迭代都是大刀阔斧,推倒重来。

只学会了语法,而没有找到用武之地,在我看来,并没有真正的学会。而所谓“学以致用”,在我看来,可以理解为“学一个东西,学到能够真正用起来,才是真的学会了”。

所以,关于如何学习一门技术或者技术中的某个特性,我有3点比较主观的建议:

1、学习相关的语法

这是基础,也是大部分新手能够快速做到的。但是,容易走进的一个误区是“死记硬背”。读大学那会儿,我甚至看到过有些同学学习编程语言的方式,竟然是背书上的代码,然后在纸上默写出来……

语法了解了,就足够了,用多了,自然就会了。而且,现在的IDE的提示、自动补全功能都很强大了,没必要死记硬背。所以,我接手一个新的团队,第一件事,一定是把招开发人员的笔试环节给干掉……

2、探究技术的适用条件

编程技术,如同其他事物一样,都是因条件存在的。很少有放之四海而皆准的道理,全是因条件而转移。同样,也没有万金油的技术。如果,你觉得有,要么是你太懒,要么你视野、圈子太窄。

在了解一个技术的语法基础之后,能够深入理解其能发挥作用的条件、局限性,才是进一步深入学习的表现。

3、找到技术的应用场景

技术光是高大上,显然不是牛逼的技术。应用范围广泛,日用而不自知的技术,才是真的牛逼。所以,学会一门技术最根本、最终要的部分,就是能够找到应用该技术的场景。

如果不能学以致用,大概率是没有真正学会,停留在了第一阶段的基础语法,自以为学会了。要不然,就是选错了,跟你工作、生活场景完全没有交集。

功能迭代的应对方案

在实际项目中,0.1或者1.0的版本,通常来说,看似功能多、任务重,其实,反而是最简单的。当然,前提是很好地进行了架构设计,否则,当我没说。

一个真正有价值、有高频应用的项目,大部分的投入一定在于应付不断快速变化的应用场景及需求(有些变化是客观原因,有些变化是能力的问题)。

相应项目的功能迭代,更关键的其实在良好设计之初,以及后续的良性扩展。无非两点:

1)提升代码的复用性。

2)提升代码的可扩展性。

其实,本质上,还是对开闭原则的践行。

以高阶函数这个特性的应用来说的话,应对项目功能迭代有3种方式:

1、最简单粗暴的做法,函数的功能发生变更,直接改函数体的代码,最直接,最通用,当然,改动的风险、影响面会比较大。

2、保持函数体的稳定,应用高阶函数进行封装,实现对修改封闭,对扩展开放。

3、终端用户端进行调整,最不求人的做法,毕竟有些三方模块,我们没法直接修改。

高阶函数在功能迭代中的实践

接下来,我们以实际代码演示高阶函数在功能迭代中的用法。我们模拟一下

假设,我们有一个名为m1.py的模块,定义了一个函数,代码如下:

def do_import_work():
    print("干大事,很重要")

在入口文件调用代码如下:

from m1 import do_import_work

if __name__ == '__main__':
    do_import_work()

执行结果:

4d4fc1bf87d1be5a5fcdffb7bac81e8b.jpeg

假设现在我们需要对do_import_work()所实现的功能进行调整,添加准备和收尾工作,根据前面的描述,有三种方法。

方法1:直接修改函数体代码,仅修改m1.py:

def do_import_work():
    print("做大事前,需要准备充分")
    print("干大事,很重要")
    print("大事做完,要很好地进行收尾,善始善终")

执行结果:

460ea19e6499bf97834e6b917fc6b541.jpeg

方法2:引用高阶函数封装,仅修改m1.py:

def do_import_work():
    print("干大事,很重要")


def do_import_work_v2(func):
    def inner():
        print("做大事前,需要准备充分")
        func()
        print("大事做完,要很好地进行收尾,善始善终")

    return inner


# 之所以使用高阶函数,然后进行封装,是为了让用户无感知,无需任何修改
do_import_work = do_import_work_v2(do_import_work)

执行结果:

a5270cac331922278015eeb8446a9705.jpeg

方法3:用户端进行修改,m1.py不动,修改所有用户端代码,这里只有入口文件需要修改:

from m1 import do_import_work

if __name__ == '__main__':
    print("做大事前,需要准备充分")
    do_import_work()
    print("大事做完,要很好地进行收尾,善始善终")

执行结果:

380017ec214021de659a1bf6ca88270b.jpeg

我们简单分析一下这三种方法:

1、直接修改模块中的函数体,最简洁,也最粗暴,前提是我们能对模块源码进行修改。

2、通过高阶函数封装,虽然示例代码中,进行封装的代码放在了模块m1中,但是,这部分代码,其实也可以出现在用户端点中,主要思考在于如何最大程度的屏蔽变化,让下游无感知。

3、用户端代码修改,也很粗暴,但是难点在于,任何使用到老版本的函数的地方,都要进行修改,改动的地方会比较多。

通过简单对比,其实也能发现高阶函数在应对功能需求迭代,保证项目可扩展性,以及将变化屏蔽在上游的作用。希望结合这个场景,能够对高阶函数的价值,有了更新的理解。

在实际的项目开发中,尤其是团队协作开发的项目中,为了尽可能地保证代码的复用性及可扩展性。首先,一定要在项目之初,尽享良好的设计,尽量做到模块的划分清晰,模块做到高内聚、低耦合。其次,在需求发生变化,需要功能迭代的时候,一定要优先考虑在上游将变化屏蔽掉,从而降低改动的成本。最后,如果实在没办法了,只能在用户端代码修改了,那就尽量提前梳理清楚,需要改动的地方,尽量无遗漏。毕竟,完成比完美更重要。

总结

本文以部分技术特性似乎没有什么作用为出发点,思考了关于技术如何学习的三个重点,以及基于高阶函数,探讨了功能迭代时,如何很好地应对。

感谢您的拨冗阅读,希望对您有所帮助。

af7a3a003211c85001be3f0bb0c81753.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南宫理的日知录

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

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

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

打赏作者

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

抵扣说明:

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

余额充值