编程语言:谈谈代码复用的机制,变量_函数_类_库_包(二)

导语:本系列讲述了编程语言当中,有关于代码复用所设计的一些机制和概念,包括变量、函数、类、库和包的概念和作用,属个人见解,欢迎指正。本文不谈及某个具体的编程语言,旨将其中一些共通的概念进行讲解,以便给于像我这种半路出家的人一种思考的维度。

1.代码块的封装和复用

例1:取三个数的最大值

a=1,b=2,c=3,max=0
#条件判断,三个数互相比较大小
if(a>b and a>c) max=a
if(b>a and b>c) max=b
if(c>a and c>b) max=c

print(max)

上例中,用了三行代码来判断三个数的大小,来获取最大值。这三行代码就是取三个数最大值的一个算法,也就是说任意给三个数,我都可以用这三行代码来取出最大值。比如,下例中,给出d,e,f三个数

d=4,e=5,f=6,max=0
#条件判断,三个数互相比较大小
if(d>e and d>f) max=d
if(e>d and e>f) max=e
if(f>d and f>e) max=f

print(max)

直接复制例1的三行代码,然后把对应的变量进行替换,即可完成任意给定三个数取最大值的算法。

这么操作没毛病,但是,好像哪里有些不妥?下回再遇到取三个数的最大值,还得再复制一遍三行代码,再把对应的变量进行替换。复制代码总不会出错吧,替换变量就说不定了,稍微走神,就可能替换错了,而且替换变量的操作次数的代价也不小。那有什么办法优化呢?

1.1代码封装->定义函数

我们可以把那三行代码进行封装,封装成一个函数。封装的意思,可以理解为,在三行代码外边加一层包装封起来,形成一个代码块:函数
例2:

function max(x,y,z)
{
max=0
#条件判断,三个数互相比较大小
if(x>y and x>z) max=x
if(y>x and y>z) max=y
if(z>x and z>y) max=z
return max
}

然后再对任意给定的三个数取最大值,可以这么操作

a=1,b=2,c=3,max=0
max=max(a,b,c)   	=>等价于 1->a->x,2->b->y,3->c->z
					  复制{if(x>y and x>z)...}
print(max)

用max函数把三行代码进行了封装,哪个地方需要那三行代码,就直接调用max函数,相当于把那三行代码通过max函数复制过去,实际的效果跟例1是等价的。max函数替代了那三行代码,可以理解为max函数是个变量,保存的是三行代码,那个地方用到了,就相当于把三行代码复制过去。

然后,通过函数传参的方式,把需要比较的三个数,传递给函数,而不用再做修改相应变量的操作。数据通过实参传递给形参之后,数据会被赋值到相应的函数内部变量。

实参:可以理解为,需要传入函数的变量和数据,是需要被函数进行处理的真实数据或者真实参数。即上例中,max(a,b,c)–>1,2,3三个数,通过变量a,b,c传入max函数。

形参:可以理解为,函数自己内部使用到的变量,这些变量只在函数内部有效,即作用域(起作用的范围)只限于函数体内部。这些变量,接收传入的实参的数据(1,2,3),然后在函数内部用到这些变量的地方,把数据调用到相应的位置。这些变量在函数定义的时候,本身是不保存任何数据的,相当于给之后要传入的数据占个位置,只有等到函数被调用,真实数据被传入之后,这些变量才代表了那些数据。在函数定义的时候只作为形式上的变量或参数而存在。

实际的数据传递过程如下:

d=4,e=5,f=6,max=0
#条件判断,三个数互相比较大小
if(d>e and d>f) max=d	=>if(4>5 and 4>6) max=4
if(e>d and e>f) max=e	=>if(5>4 and 5>6) max=5
if(f>d and f>e) max=f	=>if(6>4 and 6>5) max=6

max=max(d,e,f)			=>max(4,5,6)#通过实参def传入数据
function max(x,x,y)		=>x:4,y:5,z:6#数据传给形参xyz	
{
max=0					#x,y,z所在的位置,填入相应数据
if(x>y and x>z) max=x	=>if(4>5 and 4>6) max=4
if(y>x and y>z) max=y	=>if(5>4 and 5>6) max=5
if(z>x and z>y) max=z	=>if(6>4 and 6>5) max=6
return max
}

可以看到,两种方式是等价的。以上可得,使用函数的好处有:

  • 不用复制代码,直接调用函数即可,两者是等价的
  • 有了实参和形参,复制代码之后替换变量的操作也不需要了

需要用到取三个数最大值代码的地方,直接调用函数max,传入数据,返回的输出结果即是三个数的最大值。

通过实参传入
处理后输出
三个数
max函数
最大值

可以把max函数当做一个黑盒,里边的代码不需要知道,只需知晓这个黑盒的作用就是:输入三个数,输出最大值。别人调用这个函数的时候,只需要一行代码即可:max=max(参数1,参数2,参数3)

这个黑盒的作用,就是封装的意义,无须理会函数内部的代码,只需关注输入和输出。函数内部有三行还是三百行代码都可以,我却不需要关心,我只知道输入三个数,它能给我输出一个正确的最大值,而且屡试不爽。

这会带来一个直接的好处:

  • 如果需要对取最大值的算法进行优化,扩展到可以对不限定个数的数据进行取最大值,只需要在函数内部进行修改操作,并做兼容处理,在任何调用了函数的地方,都不需要进行修改。即:只修改一次函数内部代码,即可实现:已经调用到函数取三个数最大值的代码,和即将调用函数取任意多个数的最大值的代码,输出结果都是正确的。

封装之后的代码块,构成一个函数,调用函数时只需关心输入和输出;当函数内部代码改变,只要输入和输出的关系不变,这个函数依然有效。

1.2代码复用->调用函数

函数要起到代码复用的作用,首先要进行代码块的封装,然后在需要使用到相同代码的地方,以调用函数的方式进行代码复用。

即:某段代码,需要被重复用到多次,为减少复制代码和替换变量等操作,将其封装成函数,通过调用函数,实现复制代码和替换变量的等价操作。同时,这段代码,只进行了一次编写,就可以通过调用函数来重复使用,也实现了代码复用的作用。

所以,高效的代码复用,需要进行代码封装。

那哪些代码需要进行封装?需要重复使用的相同功能的代码,或者,为了降低代码的复杂度,对某些实现基本功能的代码进行封装,进行模块化操作,定义功能性描述的函数名,增加可读性。

也就是,为了提高编写效率和阅读起来方便,把重复的部分和理解起来比较复杂的部分,进行封装,定义函数,用函数来替代那些代码。一来,代码重复的地方,用调用函数来替代,可以减少代码数量;二来,定义了函数,给函数取一个功能性描述的函数名,使复杂的代码理解起来比较容易,增加代码的可读性;三来,需要对重复代码进行修改时,从修改每一处重复的代码,变成只修改一次代码,提高可维护性。

下面是封装、调用和修改代码的完整过程:
例3:

#未封装前的代码:
a=1,b=2,c=3,max1=0
if(a>b and a>c) max1=a
if(b>a and b>c) max1=b
if(c>a and c>b) max1=c
print(max1)

d=4,e=5,f=6,max2=0
if(d>e and d>f) max2=d
if(e>d and e>f) max2=e
if(f>d and f>e) max2=f
print(max2)

g=7,h=8,i=9,max3=0
if(g>h and g>i) max3=g
if(h>g and g>i) max3=h
if(i>g and i>h) max3=i
print(max3)

提取重复的功能相同的代码进行封装:
重复的共同部分代码形式:

if(a>b and a>c) max1=a
if(b>a and b>c) max1=b
if(c>a and c>b) max1=c

在外头套一层包装,封装成函数:

function max()
{
if(a>b and a>c) max1=a
if(b>a and b>c) max1=b
if(c>a and c>b) max1=c
}

增加函数的形参,替代代码中的变量,并完善函数代码和格式

function max(x,y,z)
{
max=0
#条件判断,三个数互相比较大小
if(x>y and x>z) max=x
if(y>x and y>z) max=y
if(z>x and z>y) max=z
return max
}

以调用函数的形式使用重复的代码,原来代码可以变为:

a=1,b=2,c=3,max1=0
max1=max(a,b,c)
print(max1)

d=4,e=5,f=6,max2=0
max2=max(d,e,f)
print(max2)

g=7,h=8,i=9,max3=0
max3=max(g,h,i)
print(max3)

如果需要对重复的代码进行修改,只需把函数的代码修改即可,max函数变为如下:

function max(x,y,z)
{
max=if(x<y) 
	if(y<z) max=z
	max=y
else if (x<z) max=z
return max
}

输入同样的数据,函数的输出不变,函数依然有效,省去了重复修改代码的操作代价。对于函数调用来说,不需要关心函数的内部实现过程,只需要关心输入和输出的关系。
之后调用函数的时候,等价的代码为:

max(a,b,c)
#等价于下边的代码
{
max=a
if(a<b)
	if(b<c) max=c
	max=b
else if(a<c) max=c
return max
}

调用的地方无须修改,实际的实现代码自动更新为修改后的代码。

总结:
重复的代码块实现相同的功能,为了减少操作上的时间耗费,将其封装成函数,通过函数的调用实现代码的重复使用,可降低代码的复杂度,变得简洁,增加可读性,提高可维护性。代码块复用的关键在于封装,封装哪些代码和如何封装,直接影响代码复用的效果。函数要实现代码复用的前提,是进行代码的封装,封装是为了复用,复用需要先进行封装。

使用编程语言内建的函数,因为函数的定义已经被包含了进来,可以直接使用即可。但是使用第三方函数库时,需要先导入第三方的函数库,也就是把第三方函数的定义进行导入,然后才可以正常调用。以上的过程,即是:封装在前,调用在后,调用函数前,需有函数的定义即代码块的封装。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sam_kql

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

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

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

打赏作者

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

抵扣说明:

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

余额充值