第五日初学函数

学习函数:


1.函数的定义
    下面我们来想象一下,如果你想用榨汁机做一杯美味的猕猴桃汁,需要哪些步骤呢?
1将猕猴桃去皮;
2将猕猴桃切块;
3将切碎的猕猴桃放进榨汁机;
4将果汁倒进杯子中。
经过上面的 4 步,一杯愉悦味蕾的猕猴桃汁就可以呈上来,端给朋友们了!

我们把这四步用代码表示,打印在屏幕上,再多打印一句“制作完成!”:
print('将猕猴桃去皮')
print('将猕猴桃切块')
print('将切碎的猕猴桃放进榨汁机')
print('将果汁倒进杯子中')
print('制作完成!')

打印的结果是这样:
将猕猴桃去皮
将猕猴桃切块
将切碎的猕猴桃放进榨汁机
将果汁倒进杯子中
制作完成!

上面的代码中,我们用使用了五次 print(),打印出了一杯猕猴桃汁制作的全部过程。下面我们来点挑战:家里来了 3 位客人,需要你制作 3 杯猕猴桃汁,如何用代码表示制作 3 杯的流程?

制作一杯就要写 5 行代码,制作 3 杯的话,要写 15 行代码,而且内容都一样!决心要成为 Python 大神的你,怎么能忍受这么低效的方式呢!根据 DRY (Don't repeat yourself) 原则,我们写代码才不会做这种无聊的事情。

我们不妨换一种聪明的方法:在一开始,就把某件事情的步骤教给 Python,并用一句“暗号”来指代要让 Python 做的事情,以后只要对 Python 说出这个“暗号”,Python 就能把整个事情做完。

那么,我们就先来教 Python 自己做猕猴桃汁,并把“暗号”定为 make_juice。教 Python 做果汁的代码要这样写:
def make_juice():
    print('将猕猴桃去皮')
    print('将猕猴桃切块')
    print('将切碎的猕猴桃放进榨汁机')
    print('将果汁倒进杯子中')
    print('制作完成!')

上面的代码,第一行使用了 def make_juice(): 这样的格式,def 是 define(中文含义:定义)的缩写,表示你要向 Python 传授做事流程了,make_juice 是你定义的流程暗号名。在这一行的末尾,一定要加上一对 英文括号 和一个 英文冒号 哦。

从第二行开始,我们要开始写制作猕猴桃汁的代码了。我们发现,它们的前面统一开头空了两格,也就是我们在第三关说到的 缩进,这是用来表示:这几行代码属于内部确定的做事流程。
这就是完整的教 Python 做事的代码结构,要注意以下几点:

用 def 引导出要定义的“暗号”,后面加上一对括号和冒号作结尾;
具体的做事代码直接写在下面,前面统一加缩进。
这样,Python 就记住了, make_juice 是它学会的“新暗号”,专门用来制作猕猴桃汁。以后,我们只要使用 暗号名() 的格式,就能让 Python 进行我们刚刚教会它的一系列操作。

现在来试试,让 Python 连做三杯猕猴桃汁吧,只要输入三次 make_juice() 就好啦:
make_juice()
make_juice()
make_juice()

我们能看到,Python 乖乖地将之前的内容完整打印了三次:
将猕猴桃去皮
将猕猴桃切块
将切碎的猕猴桃放进榨汁机
将果汁倒进杯子中
制作完成!
将猕猴桃去皮
将猕猴桃切块
将切碎的猕猴桃放进榨汁机
将果汁倒进杯子中
制作完成!
将猕猴桃去皮
将猕猴桃切块
将切碎的猕猴桃放进榨汁机
将果汁倒进杯子中
制作完成!

整个流程下来,原先做三杯果汁要手动输入 15 行代码,而现在变成了 9 行:
# 前 6 行教会 Python 做猕猴桃汁
def make_juice():
  print('将猕猴桃去皮')
  print('将猕猴桃切块')
  print('将切碎的猕猴桃放进榨汁机')
  print('将果汁倒进杯子中')
  print('制作完成!')
# 缩进结束,表示定义完毕

# 后 3 行用 Python 做三杯猕猴桃汁
make_juice()
make_juice()
make_juice()
Python 的阅读顺序和我们人类是一样的,都是从上向下,一行一行地读,所以,要按照从上到下的顺序,先教 Python 做事,再让它真正执行。
前 6 行定义了 make_juice ,教 Python 做猕猴桃汁。Python 读完所有带有缩进的代码后,学习完毕,心中牢牢记下了你的教导,然后继续向下读。

读到第一个 make_juice() 时,它立即看到了暗号并了解了意思,马上将之前说好的操作流程执行了一次,打印了制作猕猴桃汁的 5 行内容。执行完毕后,它就继续向下一行读,又是 make_juice(),然后又行云流水地打印了 5 行内容……

就这样,三行 make_juice() 都被 Python 准确识别,并作出了正确的操作。

话说“磨刀不误砍柴工”,只要花点时间,事先和 Python 对好“暗号”,那后面就能省下很多精力。“暗号”在后期使用得越多,就越能彰显出这样的优势。以后的编程学习的道路上,我们要经常和 Python “对暗号”,教会它以更少的代码,完成各种各样的复杂任务。

这样的“暗号”,在编程中有个专门的名字:函数。我们用严谨的语言来描述一下什么是 函数:函数是一段组织好的,可重复使用的,用来实现特定功能的代码块。
函数的定义中,有三个要点:

组织好的:做猕猴桃汁的过程代码预先写在了教 Python 做事的过程中;
可重复使用的:我们可以和 Python 对无数次暗号,Python 就会乖乖执行无数次;
用来实现特定功能:做猕猴桃汁。
前面教 Python 做事,并设定好“暗号”的过程,叫作 定义函数。其中缩进的几行表示具体处理过程的代码,叫 函数体。
def make_juice():
  print('将猕猴桃去皮')
  print('将猕猴桃切块')
  print('将切碎的猕猴桃放进榨汁机')
  print('将果汁倒进杯子中')
  print('制作完成!')
而后面让 Python 真正根据暗号做事的过程,叫作 调用函数,我们可以让 Python 执行无数次暗号,也就是说,函数一旦定义,就可以任我们随意调用。
make_juice()
make_juice()
make_juice()


2.函数的参数
    我们通过定义函数,教会了 Python 榨猕猴桃汁,那可不可以教它榨苹果汁?当然可以。我们可以稍微修改一下代码,再定义一个 make_apple_juice() 函数:
def make_apple_juice():
  print('将苹果去皮')
  print('将苹果切块')
  print('将切碎的苹果放进榨汁机')
  print('将果汁倒进杯子中')
  print('制作完成!')
那如果要再教它做桃子汁呢?又要修改代码定义一个新函数吗?等等,这样的话,会不会太烦了,明明都是一样的流程,只是换个水果而已,就要兴师动众,重新定义函数。此时我们又陷入了和本关一开始遇到的一样的问题:低效的重复。

仔细想想,榨果汁,其实就是“流水的原料,铁打的步骤”。水果不管怎么变,都是要去皮、切块、放进榨汁机的。所以我们需要对函数进行改造,让它对所有水果都通用。

我们可以预设一个临时变量 fruit,表示将要处理的水果,放进函数的定义过程中,让 Python 学习更灵活的做事流程。
# 定义函数时,括号中写进预设的变量 fruit
def make_juice(fruit):
  # 把 fruit 写进函数体中
  print('将' + fruit + '去皮')
  print('将' + fruit + '切块')
  print('将切碎的' + fruit + '放进榨汁机')
  print('将果汁倒进杯子中')
  print('制作完成!')

# 做苹果汁
make_juice('苹果')
# 做桃子汁
make_juice('桃子')
预设的临时变量 fruit,要放进第 1 行定义函数部分的括号中,用以向 Python 事先声明,具体的水果需要视情况而定;在函数体中,水果该出现的地方也换成 fruit。定义完毕后,Python 虽然不知道到底要遇到什么水果,但至少是把流程给牢牢记住了。

等到读到下面的调用函数的代码 make_juice('苹果') 时,Python 就恍然大悟:“我要把 '苹果' 赋值给 fruit,然后再执行代码!那我来试试看!”
所以,最后的执行效果和下面的代码相同:
fruit = '苹果'

print('将' + fruit + '去皮')
print('将' + fruit + '切块')
print('将切碎的' + fruit + '放进榨汁机')
print('将果汁倒进杯子中')
print('制作完成!')
这样,我们就得出了想要的打印结果:
将苹果去皮
将苹果切块
将切碎的苹果放进榨汁机
将果汁倒进杯子中
制作完成!

根据这个逻辑,Python 读到 make_juice('桃子') 时,也自然可以打印出榨桃子汁的正确流程。

定义函数时预设的临时变量,有个专门的名称:参数。定义过程所用的样板 fruit,叫作 形式参数,简称 形参,只起示范作用;而实际调用函数时 make_juice('桃子') 中的 '桃子',叫作 实际参数,简称 实参。

有了 参数,函数就更加灵活而强大了。定义函数时,我们只要专心总结出固定的操作流程,至于具体根据场景而变化的元素,只要交给 参数 去统一表示就可以啦。

这种“预设临时变量,写进固定流程”的思路,想必我们早就不陌生了,在学数学和物理公式时,用的都是这种思路。比如圆的周长公式 C = 2πr,我们只要用 π 乘以半径乘以 2,就能得出周长,具体的半径是多少,实际运算中代入就好。

由于思路相通,所以求圆周长的公式,我们可以写成一个函数,将半径 r 作为参数:
def circle(r):
  c=2*3.14*r
  print('该园的周长为:'+str(c))
我们调用两次这个函数试试:
circle(2)
circle(3)

# 输出:
# 该圆的周长是12.56
# 该圆的周长是18.84

Python 在执行 circle(2) 和 circle(3) 时,执行效果和下面的代码相同:
r = 2
c = 2 * 3.14 * r
print('该圆的周长是' + str(c))

r = 3
c = 2 * 3.14 * r
print('该圆的周长是' + str(c))


编程练习***
上面的知识点学会了吗?我们来写一个函数来求圆的面积吧。

提示:圆的面积为 π * r * r。

要求:

定义函数 area(),接受半径 r 为参数;
π 取 3.14,计算圆的面积;
用函数计算半径为 8 的圆的面积。


3.函数的返回值
return 语句
学到这里,你有没有想过,函数的运行结果,在内部按指定的格式打印,是不是有点太死板?可不可以把运算结果拿出来自己任意使用呢?

我们以刚刚的定义的函数 circle() 为例,现在的写法是这样的:
def circle(r):
  c = 2 * 3.14 * r
  print('该圆的周长是' + str(c))
每次运行时,只能按照既定格式打印出 “该圆的周长是xxx”,如果要换一个打印格式,只改动一点,改成“圆的周长:xxx”,要怎么办?

根据目前学到的知识,我们只能定义一个新函数。
def new_circle(r):
  c = 2 * 3.14 * r
  print('圆的周长:' + str(c))
为了一个字大动干戈,写了个新函数 new_circle(),又开始低效重复了。能不能让我们只获取 circle() 中的关键信息:周长 c ,然后具体要怎么打印,供我们自由发挥?

话不多说,动手修改吧。我们把函数内部用于打印的语句去掉,然后在函数外,用变量 result 去获取运算结果,打印出来看看有没有成功:
def circle(r):
  c = 2 * 3.14 * r

result = circle(2)
print(result)
在看真正结果前,你能预测出打印结果是什么吗?是 12.56 吗?实际上,打印出来是这样:
None
看来,result 获取运行结果失败,打印出的是一个不认识的 None。这是什么玩意儿?

在 Python 中,None 是一个特殊的值,表示“什么也没有”,在这里,表示变量 result 是空的,没有任何值,硬要通过 print(result) 打印的话,就只能打印出 None 通知你一下,“不要问,问就是没有”。
为什么变量 result 没有获取到值?circle(2) 中算出来,好好的 12.56,怎么就丢了呢?

这是因为,函数内部的代码是一个封闭的“小团体”,不管里面的代码运行出了什么,都不会主动和外面的代码分享。就算函数体里面加个 print(),也只是把结果打印在屏幕上而已,不会和别的代码互通有无。也就是说,除了打印,毫无用处,无法进行其它操作。

所以 result = circle(2) 这一句,就算是 circle(2) 自己运算出了结果,也不会透露给 result,只会让他空手而归。

这时候,我们需要在函数内部的结尾,加上 return 语句来帮忙,它的作用就是函数内部与外部世界的“信使”,负责将函数内部的值传递给外面。
def circle(r):
  c = 2 * 3.14 * r
  # 函数体最后一行加上 return 语句
  return c

result = circle(2)
print(result)
print('该圆的周长为' + str(result))
经过修改的代码,就能正确地打印出计算结果了:
12.56
该圆的周长为12.56

函数体中, return c 的意思是,将 c 指定为唯一可以和外界交流的数据,外面的代码想要获取内部运行结果,就丢个 c 的值给他。至于外面如何处置,函数就管不着了。

被 return 语句传到函数外的值,叫作函数的 返回值。返回值 要么被外部代码直接打印,要么赋值给变量,要么参与运算等。总之,每一次 circle() 函数的调用,都会和其它代码联系在一起,而 返回值 c 就是唯一的纽带。

def circle(r):
  c = 2 * 3.14 * r
  # 函数体最后一行加上 return 语句
  return c

# 直接打印返回值
print(circle(1))
# 输出:6.28

# 将返回值赋值给变量
result = circle(3)
print(result)
# 输出:18.84

# 返回值参与运算
print(circle(1) * -1)
# 输出:-6.28

# 返回值参与字符串的拼接
print('本次的运算结果为' + str(circle(1)))
# 输出:本次的运算结果为6.28

***编程练习***
现在我们已经知道了如何定义并调用一个有 返回值 的函数,我们接下来用函数写一个年龄计算器吧!

要求:

定义一个名为 calc_age 的函数;
calc_age() 函数的输入参数为出生年份,返回年龄;
调用函数三次,传入不同参数,使用 print() 函数在屏幕上打印出函数的返回值。


4.函数的要点
典型的函数
现在的 circle() 函数,是一个典型的函数:既有 参数,又有 返回值。我们来分析一下它的结构:

def circle(r):
#def表示定义一个函数,circle函数名称,r表示输入的参数
  c=2*3.14*r
#表示处理过程
  return c
#返回结果c

它代表了一个函数的通用思路:

告诉 Python,要定义一个函数;
暗号名,即函数的名字是什么;
(非必要)这个函数需要什么 参数;
处理过程是什么样的;
(非必要)把什么样结果 返回 给外部。
有了这个通用思路,我们一定能写出功能明确的函数!

Python 中自带了很多函数,给我们提供了很多常用的功能,我们已经接触过了一些,比如 type()、 input()、str() 等,它们都是既有参数,又有返回值的函数。

print(type(5))

# 输出: <class 'int'>
我们以 type() 函数为例,它的调用时,实际参数 是整数 5,经过内部一系列不需要我们关心的操作后,得出的 返回值 为字符串 '<class 'int'>',借助 print() 函数打印了出来。

5.函数的命名
函数的命名和变量的命名是一样的,由数字、字母、下划线组成,并且不可以用数字作为名称的开头。另外,名称本身要表达自己的功能,要简单易读,并且中间不能有空格。如果有多个单词,要用下划线 _ 连接。

下面的几个函数名是规范的:
total() # 让人一眼看出,功能是求总量
make_juice() # 表达功能,并且用了下划线分割单词。

下面这几个函数的命名方式是不推荐的,虽然符合 Python 语法,但是让人看得云里雾里。
yysy() 
xswl() 
aa_bb()

而下面这种命名方式是错误的,因为函数名中不能出现空格:
make juice()


6.函数格式易错点
在定义函数的过程中,新手程序员们最容易犯的错误有以下几点:

第一行定义函数时,括号和冒号不小心写成了中文的。这会导致程序报错 (SyntaxError):
# 我们故意把括号和冒号改成中文
def circle(r):
  c = 2 * 3.14 * r
  # 函数体最后一行加上 return 语句
  return c

# 输出:
# SyntaxError: invalid character in identifier
# 语法错误:识别到无效字符

中文的括号和冒号会被识别为无效字符。所以我们要注意,不要犯这种低级错误哦。

另一个,就是忘记在函数体前统一加缩进。这样也会导致程序报错 (IndentationError):

7.return 语句的陷阱
return 语句有一个特别要注意的点,return 语句是函数执行结束的标记,运行完 return 语句,就会退出函数的执行,不管后面还有没有其它代码。所以我们一般都要把 return 语句放在最后。

上面这句话有点绕,我们用例子来解释吧。

有时候你可能会想,可不可以让函数先在内部打印信息的同时,再返回一个值给外面?

当然可以,我们以 circle() 函数为例,改写一下:
def circle(r):
  c = 2 * 3.14 * r
  # 先打印计算结果
  print('该圆的周长是' + str(c))
  # 函数体最后一行加上 return 语句
  return c

result = circle(2)
print(result)
这样写,我们就会得到两行打印结果:
该圆的周长是12.56
12.56
第一行的 “该圆的周长是12.56”,是由函数在执行时,内部的 print('该圆的周长是' + str(c)) 打印出的结果。

第二行的 12.56,是变量 result 通过函数体最后一句 return c, 获取了 c 的值,再由 print(result) 打印来的结果。

但如果我们将函数内部的 print('该圆的周长是' + str(c)) 和 return c 调个位置,结果就不一样了。

def circle(r):
  c = 2 * 3.14 * r
  # 先返回结果 c
  return c
  # 最后打印计算结果
  print('该圆的周长是' + str(c))


result = circle(2)
print(result)
此时我们只能得到一行结果:
12.56

这是为什么?这就是我们在之前说的,运行完 return 语句,就会退出函数的执行啦。return c 运行完,circle(2) 就自动认为运行结束,后面的 print('该圆的周长是' + str(c)) 就没有机会运行了!

所以,我们一定要牢记,return 语句就代表了函数执行的结束!在函数返回值之外还想有什么额外的操作,都一律要写到 return 语句的前面!

回顾:
这一关里,我们的水平又进了一步,认识了 Python 中的函数。

我们再回想一下,什么是函数?

函数是一段 组织好的、可重复使用的、用来实现特定功能的 代码块。

写函数时的五个要素是什么?

定义函数的标识 def: 告诉 Python,要定义一个函数;
暗号名,即函数的名字是什么;
(非必要)这个函数需要什么 参数;
处理过程是什么样的;
(非必要)把什么样结果 返回 给外部。
另外,在写函数时,整理一下要注意的地方:

定义函数时,要遵循语法规则,给函数和参数的命名要简单易懂;
注意缩进规则,函数体中是实现函数功能的代码,前面一定要有统一的空格缩进;
我们用 函数名() 的形式调用函数,执行函数体中的代码;
外部代码想要获取函数的处理结果进一步操作,需要使用 return 语句作媒介。
return 语句是函数结束的标志,后面的代码不会运行。
这一关我们知道,函数可以有一个参数,其实,它还可以有多个参数,在后面会为你深度讲解。我们还需要谨记 DRY 原则哦,Don't repeat yourself!

函数是我们 Python 基础课的一个难点,对于新手程序员来说的确具有挑战性,不过你一定可以努力克服,逐渐掌握!

***程序练习***
1.你在编程咖啡店干得不错,已经晋升为店长啦 🎉

已知的信息如下:

咖啡店目前只卖拿铁,每杯售价 24 元,成本为 8 元;
咖啡店每天的水电、人工成本为 500。
接下来请你写一个利润计算器来计算一下咖啡店每天的利润,要求:

定义一个名为 calc_profit 的函数;
该函数有一个参数,为当天卖出的拿铁数量;
函数的返回值为咖啡店当天的净利润(不需要单位);
通过 input() 函数获取当天卖出的拿铁数量;
调用函数并打印出咖啡店当天的净利润。

2.你已经作为咖啡店店长干了一段时间了,领导想对你管理的店进行考核,考核要求很简单:每天的净利润大于 2000 为合格,否则不合格。

上一题你已经完成了计算净利润的 calc_profit() 函数,接下来请你再写一个绩效计算器来计算一下咖啡店每天是否合格,要求:

再定义一个名为 calc_perf 的函数;
该函数有一个参数,为当天的净利润(calc_profit() 函数的返回值);
该函数功能为:当净利润大于 2000 时打印 合格,否则打印 不合格;
使用 input() 函数获取当天卖出的拿铁数量;
调用函数并打印出咖啡店当天是否合格。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值