函数的作用
我种地要用锄头, 我是每次用时重新做一把锄头, 还是提前做好一把锄头, 需要时直接拿来用?很显然, 每次重新做都是重复劳动, 所以我们选择提前做好一把, 每次直接拿来用, 这里面就是一种复用的思想. 如果需要频繁解决这个问题, 那么解决这个问题的代码就可以提前写好, 需要解决该问题时, 直接拿来用.
例如: 我在代码文件的多个地方都需要计算1-100累加和这个功能, 那么怎么解决这个问题呢?
最简单的方式就是把那块代码复制到需要的地方,但代码量也大大增加,如果这个累加和的功能实现改变了, 意味着所有地方都需要修改, 增加了代码的维护量.
怎么解决呢? 通过将这个功能封装成一个单独的功能代码块, 只要需要该功能, 直接使用该功能代码块, 这个功能代码块我们也叫做函数;简言之,函数的作用就是将常用的代码封装起来, 便于以后使用。
函数语法格式
在 Python 中, 函数使用 def
关键字来定义, 包含函数的名字(功能的名字), 函数的实现(实现功能的代码).
函数的行为分为: 函数定义和函数调用.
-
函数定义是实现函数功能的过程.
-
函数调用是使用功能
注意:函数不调用是不会自动执行的.
def 函数名():
一行或者多行代码
那么1-100这个功能我们就可以写成这样的一个函数(功能代码块).
#定义函数
def my_sum():
i = 1
s = 0
while i <= 100:
s = s + i
i += 1
print("1~100的累积和为:%d" % s)
# 调用函数
my_sum()
函数的参数
再思考一个问题: 我们发现这个函数只能计算1-100的累加和, 我们能否让函数的功能支持从指定开始到结束的数字累加和?
我们可以将我们要开始和结束数字传递给函数, 让函数按照我们传递的参数来计算
def my_sum(start, end):
my_start = start
my_end = end
my_sum = 0
while my_start <= my_end:
my_sum = my_sum + my_start
my_start += 1
print("%d~%d的累积和为:%d" % (start, end, my_sum))
# 函数调用
my_sum(2, 50)
函数参数的作用就是让函数依据我们给定的值来进行运算. 这样可以增强函数的通用性. 函数可以有多个参数
例如: 我们想要编写一个具有加法功能函数, 很显然需要两个参数
def my_add(num1, num2):
result = num1 + num2
print('num1 + num2 =', result)
my_add(10, 20)
我们在调用函数时传递的真实数据叫做实参, 函数参数叫做形参, 形参只是代表真实传递的数值.
多个函数参数再传递时是从左向右传递的. 当然, 在 Python 中我们也可以指定某个值给那个形参.
def my_add(num1, num2):
result = num1 + num2
print('num1 + num2 =', result)
my_add(num1=10, num2=20)
my_add(num2=20, num1=10)
1、按照从左向右的顺序传递叫做位置参数.
2、按照形参名字传递叫做关键字参数.
能否在调用函数时既传递位置参数, 又传递关键字参数呢?
def my_add(num1, num2, num3, num4):
result = num1 + num2 + num3 + num4
return result
my_add(100, 200, 300, num2=10)
可以, 只需要保证位置参数在关键字参数之前即可
函数的返回值
请思考下面两个问题
-
现在我们的函数在计算完结果之后, 把结果放到哪里了?
-
我的程序需要继续使用函数的结计算果来进行下一步计算, 该怎么办?
使用 return 语句将函数的运行结果返回给函数的调用者
def my_add(num1, num2):
result = num1 + num2
return result
# 使用一个变量保存函数执行的结果
my_add_result = my_add(10, 20)
# 使用结果进行下一步计算
finish_result = my_add_result + 100
# 输出最终结果
print('最终结果:', finish_result)
print函数 和 return 的区别是什么?
print 只负责将内容输出到屏幕显示. 而 return 会将函数计算结果, 返回给函数的调用者.
比如: 函数类似于一个工厂, 我们将工厂生产所需要的材料通过参数的形式传递给工厂, 工厂使用我们传递的材料生产出产品.
print 相当于生产完产品后, 说了一句 “产品生产完毕”, 但是并不会把产品给用户.
而 return 相当于生产完产品之后, 并将产品交到用户手里. 那么用户就需要用一个篮子来装产品(用变量来保存函数的返回值). 当然, 虽然工厂将产品给了用户, 用户也可以不要(忽略函数的返回值).
关于 return 注意下以下几点.
-
只要函数执行碰到 return 就会停止执行.
-
函数中可以编写多个 return, 但有且只有一个 return 会执行.
-
return 后面可以跟上要返回的值, 也单独使用相当于 return None.
-
break 用在循环中, 用来终止循环执行. return 用在函数中, 用来终止函数执行.
局部变量和全局变量
全局变量:在函数外部定义的变量. 全局指的是该变量在当前 python 文件范围内是可见的. 全局变量可以被当前 python 文件内的所有函数直接使用.
局部变量:在函数内部定义的变量. 该变量只能在定义的函数内部使用.
# 定义全局变量
g_val = 100
# 在函数内部可以访问全局变量
def my_function1():
print(g_val)
# 在函数内部定义局部变量 my_val
def my_function2():
my_val = 100
# 尝试输出 my_function2 函数中定义的局部变量
def my_function3():
print(my_val)#这里直接报红线了,因为在函数中定义的变量,在这里看不见
# 函数调用
my_function1()
my_function2()
my_function3()
如果局部变量和全局变量命名冲突, Python 解释器会怎么做?就近原则,局部变量优先级大于全局变量
total_value = 100
def my_function():
total_value = 200
print('total_value:', total_value)
my_function() #200
函数的缺省参数(默认参数)
默认参数指的是当函数调用中省略了实参时默认使用的值.
默认参数的语法与使用:
-
在函数声明或定义时, 直接对参数赋值. 这就是设置形参的默认参数.
-
在函数调用时, 省略部分或全部的参数. 这时可以用默认参数来代替.
def my_function(a, b=20, c=30):
return a+b+c
my_function(10) #默认给b,c赋值20,30
my_function(10, 100)
my_function(10, 100, 1000)
注意: 带有默认值的参数一定要位于参数列表的最后面.
函数文档及作用
函数也需要添加注释, 方便函数功能、参数以及返回值的含义能够被调用者知悉. 但普通的单行多行注释, 需要查看函数定义时才能看到, 有没有一种方式能够在调用时快捷查看函数相关信息?
DocString 是一个重要的工具, 它帮助你的程序文档更加简单易懂.
# 单行函数文档字符串
def my_function(param):
"""函数做了什么事, 返回什么结果."""
return param + 10
# 多行函数文档字符串
def my_add(num1, num2):
"""计算两个整数的和.
:param int num1: 加法运算的左操作数
:param int num2: 加法运算的右操作数
:return 返回两个操作数相加的结果
"""
result = num1 + num2
return result
我们可以通过 ctrl + q
快捷键可以查看函数信息, 也可以通过 help()
函数来查看函数信息.
单一职责原则
请问: 在工作中一个人负责的职责越多还是越少越好? 同理问, 编写一个函数, 函数能完成的功能越多还是越少越好?
单一职责原则说的是一个函数只负责一个事情.这是因为, 如果一个函数承担的职责过多, 就等于把这些职责混合在一起, 一个职责的变化可能会影响其它职责的能力.
-
简称 单一职责原则的英文名称是Single Responsibility Principle, 简称
RSP
. -
定义 就一个函数而言, 应该仅有一个引起它变化的原因, 简单的说, 一个函数中应该是一组相关性很高的的封装.即一个类只负责一项职责, 而不应该同时负责多个职责.
-
问题 比如 A 函数负责两个不同的职责 B 和 C;B 功能需求发生变化时, 更改 A 函数, 有可能使原本正常运行的 C 发生错误, 代码耦合性太高, 较复杂.
-
解决 把功能独立出来, 让它们满足单一职责原则. 比如创建两个函数 A1 和 A2, A1 完成功能 B, A2 完成功能C. 任何一个功能出现问题都不会造成另一个功能出问题