函数、传参、返回值,和代码复用 在这一章节中,我们主要学习函数(Function),我们知道,”function” 一词本身就有“功能”的意思,便于理解,可以直接将“函数”视为“功能”。出于严谨,下文中我们仍然统一称之为“函数”。
内置函数 我们之前已经使用过一些函数,如 print
、input
,它们属于内置函数,BIF(built-in functions),顾名思义,是 Python 自带的一些函数,我们可以直接使用它们。以 print
函数为例,包括但不限于以下的调用形式都是合法的。
1 2 3 4 5 6 7 8 9 10 11 >>> print ("hello, world!" )hello, world! >>> print (1024 )1024 print (6 + 4 )10 >>> print (True )True word = "hello" print (word)hello
自定义函数 既然存在内置函数,那意味着也存在自定义函数,确实是这样,本章节也围绕自定义函数展开。
定义 一般的,通过 def
关键字定义函数,括号 () 内为其参数 (Param),return
关键字用于返回值。
先来看一个最简单的自定义函数:
1 2 3 def add (a, b ): result = a + b return result
def
定义了一个函数名为 add
的自定义函数,它有名为 a 和 b 的两个参数,并返回 result
的值。
对于这种逻辑简单的函数,还可以直接写成这样:
1 2 def add (a, b ): return a + b
函数光是定义是永远不会运行的,还需要我们调用:
1 2 3 4 def add (a, b ): return a + b print (add(4 + 6 ))
函数体内还可以做更多的逻辑判断,比如我们实现一个求绝对值的函数:
1 2 3 4 5 6 7 8 9 def abs (a ): if a >= 0 : return a else : return -a print (abs (10 )) print (abs (-8 )) print (abs (0 ))
这个函数还可以写成这样:
1 2 3 4 def abs (a ): if a < 0 : a = -a return a
如果函数不需要返回值,则 return
关键字不是必须的:
1 2 3 4 def greet (): print ("Hello!" ) greet()
在这个问好函数 greet
中,由于不需要传参,所以括号内没有参数。
形参和实参 对于函数的“参数”,还有“形参”和“实参”的概念,即形式参数和实际参数。我们仍然以上文的 abs
函数为例:
1 2 3 4 5 6 7 def abs (a ): if a < 0 : a = -a return a number = -10 abs (number)
在这个例子中,abs(number)
向 abs
函数传入了 number
的值,即 -10
现在是 abs 函数的实参;定义时,abs(a)
中的 a
也是参数,但为形参,仅用来代表实际传入的 -10
。
简单来说,形参的值是不固定的,由传入的实参确定。
明白了这一点后,我们也能理解下面的代码了:
1 2 3 4 5 6 7 8 def fun (a ): a = 10 a = 8 print (a) fun(a) print (a)
若让改变变量 a 起效,应这样写:
1 2 3 4 5 6 def fun (a ): return 10 a = 8 a = fun(a) print (a)
代码复用 自定义函数最常被用作封装功能,便于代码复用。
在上一章节的最后,我们提出前台登录的程序还有很大的改进空间,其中关键的一点就是代码可维护性差。现在,我们用新学的知识继续改进它:
1 2 3 4 5 6 7 8 9 def get_age_from_id (): id = input ("请输入你的身份证号:" ) while not id .isdigit() or len (id ) != 18 : id = input ("输入有误,请重新输入身份证号:" ) birth_year = int (id [6 :10 ]) age = 2020 - birth_year return age
我们将从身份证获取年龄的代码抽象出来,封装成一个自定义函数,这样,这样,我们只需要关注业务逻辑部分,而无需在意具体的实现细节:
1 2 3 4 5 6 7 8 9 10 11 12 13 name = input ("请输入你的姓名:" ) age = get_age_from_id() if name == "莉莉" : print ("小姐里面请!" ) elif age > 60 : print ("大爷先回家歇歇吧!" ) elif age == 40 : print ("贡献您,今日消费全免,里面请!" ) elif age >= 18 : print ("欢迎您的到来,里面请!" ) else : print ("小孩子回家玩去" )
这样做的好处是很多的。如果我们后面的代码中需要重复使用这个功能,不用每次都拷贝一遍代码,若是需要修改其中的某些细节,也不需要挨个修改。
实战 在上一章节中,我留了一个课后练习题:实现一个猜数字的小游戏。你不知道有练习题?练习题会在编程小窝群中发布,我会挨个批改,帮助大家在实战中精进。
有一个同学交了这样的一份答卷:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import random given_number = random.randint(0 , 9 ) input_number = input ("请输入您猜的数字:" ) while not input_number.isdigit() or len (input_number) > 1 : if not input_number.isdigit(): input_number = input ("输入有误,请重新输入:" ) else : input_number = input ("输入有误,请输入 0 到 9 之间的个位数:" ) input_number = int (input_number) count = 1 while input_number != given_number: if input_number > given_number: input_number = input ("猜大了,你已经输错了 %d 次" % count) while not input_number.isdigit() or len (input_number) > 1 : if not input_number.isdigit(): input_number = input ("输入有误,请重新输入:" ) else : input_number = input ("输入有误,请输入 0 到 9 之间的个位数:" ) input_number = int (input_number) else : input_number = input ("猜小了,你已经输错了 %d 次" % count) while not input_number.isdigit() or len (input_number) > 1 : if not input_number.isdigit(): input_number = input ("输入有误,请重新输入:" ) else : input_number = input ("输入有误,请输入 0 到 9 之间的个位数:" ) input_number = int (input_number) count += 1 print ("猜测正确" )
本来是很简单的一个功能,写了这么一大坨,这也难怪,因为他当时还不会使用自定义函数,现在我们着手改进它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import random def get_number (): number = input ("请输入您猜的数字:" ) while not number.isdigit() or len (number) > 1 : if not number.isdigit(): number = input ("输入有误,请重新输入:" ) else : number = input ("输入有误,请输入 0 到 9 之间的个位数:" ) return int (number) given_number = random.randint(0 , 9 ) input_number = get_number() count = 1 while input_number != given_number: if input_number > given_number: print ("猜大了,你已经输错了 %d 次" % count) input_number = get_number() else : print ("猜小了,你已经输错了 %d 次" % count) input_number = get_number() count += 1 print ("猜测正确" )
是不是一下子就简洁了许多呢? 👏
扩充功能 函数非常灵活,我们可以通过传入多个参数扩充功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def get_id (): id = input ("请输入身份证号:" ) while not id .isdigit() or len (id ) != 18 : id = input ("输入有误,请重新输入身份证号:" ) return id def get_info_from_id (id , info ): if info == "age" : birth_year = int (id [6 :10 ]) return 2020 - birth_year elif info == "from" : return id [0 :6 ] elif info == "sex" : sex = int (id [-2 ]) if sex % 2 == 0 : return "女" else : return "男" id = get_id()print (id ) print ("年龄:" , get_info_from_id(id , "age" ))print ("性别:" , get_info_from_id(id , "sex" ))print ("出身地编号:" , get_info_from_id(id , "from" ))
小结 利用自定义函数,对代码进行封装,代码更加简洁,并且业务逻辑部分与技术实现部分相解耦,降低我们组织代码时的心智负担,编写更具有可读性,并且高度可维护的代码。
函数非常灵活,功能也无比强大。在今后的代码编写中,要多加思考,是否可以利用函数优化代码。