文章目录
- 1.函数
-
- [1.1 语法格式](#1.1 语法格式)
- [1.2 函数参数](#1.2 函数参数)
- [1.3 函数的返回值](#1.3 函数的返回值)
- [1.4 变量作用域](#1.4 变量作用域)
- [1.5 函数的执行过程](#1.5 函数的执行过程)
- [1.6 链式调用](#1.6 链式调用)
- [1.7 嵌套调用](#1.7 嵌套调用)
- [1.8 函数栈帧](#1.8 函数栈帧)
- [1.9 函数递归](#1.9 函数递归)
- [1.10 参数默认值](#1.10 参数默认值)
- [1.11 关键词参数](#1.11 关键词参数)
1.函数
无论是编程中的函数还是数学中的函数,本质都是差不多的,丢给函数一些值,函数在经过一系列的处理返回一个值。不过编程上函数也可以不返回值就是了。
可以把编程上的函数理解为一段可以重复使用的代码片段.
求一段区间的和。
python
#求1~100的和
sum = 0
for i in range(1,101):
sum+=1
print(sum)
#求1~1000的和
sum = 0
for i in range(1,1001):
sum+=i
print(sum)
#求20~40的和
sum = 0
for i in range(20,41):
sum+=i
print(sum)
这3段代码都同质化严重,就只有for循环之中的范围变了,那么我们就可以把其写为一个函数来多次调用。
python
#定义函数
def calcSum(left,right):
sum = 0
for i in range(left,right):
sum+=i
print(sum)
#调用函数
calcSum(1,101)
calcSum(1,1001)
calcSum(20,41)
'''
5050
500500
630
'''
是不是很简洁,这就是函数的运用,把重复的代码给消除了。
1.1 语法格式
创建函数/定义函数
python
def 函数名(形参列表):
函数体
return 返回值
调用函数/使用函数
python
函数名(实参列表)#不考虑返回值
返回值 = 函数名(实参列表)#考虑返回值
函数只有在被调用时才会执行。
函数必须先定义再使用。
python
test()
def test():
print('hahaha')
此时会报错,因为还没有定义就执行了。
1.2 函数参数
在函数定义的时候,可以在()中指定形式参数
简称形参,然后在调用时,由调用者把实际参数
简称实参,传递过去。
这样就可以做到一份函数,针对不同的数据进行计算处理。
python
#定义函数
def calcSum(left,right):
sum = 0
for i in range(left,right):
sum+=i
print(sum)
#调用函数
calcSum(1,101)
calcSum(1,1001)
calcSum(20,41)
在这个代码中,left right
就是函数的形参,1,100...
就是函数的实参。
注意:
- 一个函数可以由一个形参,也可以有多个形参,也可以没有形参。
- 一个函数的形参有几个,那么传递实参的时候也要传相应的个数,保证个数匹配。
- 和C++/java不同,python是动态类型的编程语言,函数的形参不必指定参数类=类型,也就是说一个函数可以支持多种不同类型的参数,类似于函数重载。
python
def test(tmp):
print(tmp)
test(10)
test('hahaha')
test(False)
'''
10
hahaha
False
'''
1.3 函数的返回值
函数的参数可以视为函数的输入 ,那么函数的返回值就可以视为函数的输出。
为了方便理解,我们可以把函数想象成一个工厂,所谓的函数输入就是提供给工厂的原材料,函数输出就工厂提供的产品。
还是上面的求和函数
python
##无返回值
#定义函数
def calcSum(left,right):
sum = 0
for i in range(left,right):
sum+=i
print(sum)
#调用函数
calcSum(1,101)
##有返回值
def calcSum(left,right):
sum = 0
for i in range(left,right):
sum+=i
return sum
#调用函数
print(calcSum(1,101))
这两种代码的区别就在于,前者直接子啊函数的内部就打印了,后者使用了return语句把结果返回給函数的调用者,再有调用者负责打印。
为了满足
逻辑和用户交互分离
的编程原则,第二种写法更好。在第一种写法中,然后后续我们需要保存结果到文件中,或者通过网络发送,第一种写法就难以胜任了。而第二种写法只负责计算逻辑不负责和用户交互,那么就会有更多的搭配可以实现。
一个函数可以有多个return
语句。
python
#判断一个整数是否为奇数
def isOdd(num):
if num%2 == 0:
return False
else:
return True
x = int(input("输入一个整数:"))
ret = isOdd(x)
print(ret)
执行到return
语句函数便会退出,回到开始调用的位置。
验证:
python
#判断一个整数是否为奇数
def isOdd(num):
if num%2 == 0:
return False
return True
ret = isOdd(10)
print(ret)
num是偶数,返回Flase后不会再返回True了。
python可以同时返回多个值 ,使用,
来分割多个返回值。
python
def test():
a = 100
b = 200
return a,b
x,y = test()
print(x)
print(y)
'''
100
200
'''
如果需要关注其中的部分返回值,可以使用_
来忽略不需要的返回值。
python
def test():
a = 100
b = 200
return a,b
_,y = test()
print(y)
# 200
1.4 变量作用域
python
def test():
a = 100
b = 200
return a,b
a,b = test()
观察代码,函数内外部存在相同命名的变量。但其实这两组变量是不同的变量,只是名字相同,它们的地址是不会相同的。
每个变量都有它们的作用域,变量只能在自己的作用域中生效。
python
def test():
a = 100
b = 200
return a
print(a)
# error name 'a' is not defined
在不同的作用域中,允许存在不同同名的变量。
python
x = 10
def test():
x = 100
print(f'函数内部x = {x}')
test()
print(f'函数外部x = {x}')
'''
函数内部x = 100
函数外部x = 10
'''
- 在函数内部的变量,称为局部变量。
- 不在任何函数内部的变量,也称为全变量。
如果函数内部尝试访问的变量在局部不存在就会尝试去全局去寻找。
python
x = 100
def test():
print(f'x = {x}')
test()
# 100
如果想要在函数内部修改全局变量的值,需要使用global关键字声明。
python
x = 100
def test():
global x
x = 10
print(f'函数内部x = {x}')
test()
print(f'函数外部x = {x}')
'''
函数内部x = 10
函数外部x = 10
'''
如果没有global的声明的话,系统会认为x = 10是一个新创建的局部变量。
if/while/for等语句不会影响到变量作用域,也就是说,在if/while/for中定义的变量,在语句外也可以正常使用。
python
for i in range(1,10):
print(f'函数内部 i = {i}')
print(f'函数外部 i = {i}')
1.5 函数的执行过程
- 调用函数才会执行函数体代码,不调用就不会执行。
- 函数体执行结束(或者遇到return语句)则会回到函数调用位置,继续往下执行。
python
def test():
print('hahaha')
print('hahaha')
print('xixixi')
test()
print('xixixi')
1.6 链式调用
其实前面我们已经用过链式调用了
python
##有返回值
def calcSum(left,right):
sum = 0
for i in range(left,right):
sum+=i
return sum
#调用函数
print(calcSum(1,101))#链式调用
把一个函数的返回值,作为另一个函数的参数就是链式调用。
1.7 嵌套调用
函数内部还可以调用其他的函数,这叫做嵌套调用。
python
def testPrint():
print('嵌套调用')
print('嵌套调用')
print('嵌套调用')
test函数内调用了print函数
一个函数里面可以嵌套调用任意多个函数。
函数嵌套的过程是非常灵活的。
python
def a():
print('a')
def b():
a()
print('b')
def c():
b()
print('c')
c()
'''
a
b
c
'''
1.8 函数栈帧
函数之间的调用关系,在python中会使用一个特定的数据结构来表示,称为函数调用栈 。每次的函数调用,都会在调用栈里新增一个元素,称为栈帧 。
每个函数的局部变量都包含在自己的栈帧中。
1.9 函数递归
递归是嵌套调用中的一种特殊情况,就是自己调用自己。
程序调用自身的编程技巧称为递归(recursion)
递归作为一种算法在程序设计语言中广泛应用.一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型问题层层转化为一个于原问题相似的规模较小的问题来求解.
递归策略
只需要少量的代码就可以描述出解题所需要的多重计算,大大的减少程序的代码量.
递归的主要思想在于:把大事化小
python
#计算10的阶乘
def factor(n):
if n == 1:
return 1
return n*factor(n-1)
print(factor(10))
## 3628800
注意:递归代码要保证
- 存在限制条件,当满足这个限制条件的时候,递归便不在继续。
- 每次递归调用之后越来越接近这个限制条件。
递归的优点: - 递归类似于
数学归纳法
明确初始条件,盒递推公式,就可以解决一系列的问题。 - 递归的代码量往往很少。
递归的缺点: - 递归代码往往难以理解,很容易超出操控范围。
- 递归代码容易出现栈溢出的问题。
- 递归代码往往可以转换成等价的循环代码,并且通常来说,循环版本的代码效率更高。
1.10 参数默认值
Python中的函数,可以给形参指定默认值。
带有默认值的参数,可以子啊调用的时候不传参。即缺省参数
python
def add(x,y,debug = False):
if debug:
print("haha")
return x+y
print(add(1,2))
print(add(10,20,True))
'''
3
haha
30
'''
注意:带有默认值的参数需要放到没有默认值得参数后面
1.11 关键词参数
在调用函数得时候,需要给函数指定实参,一般默认情况下是按照形参得顺序,来传递实参的。但是我们也可以通过关键字参数,来调整这里的传参顺序,显式指定当前实参传递给哪个形参。
python
def test(x,y):
print(f'x = {x}')
print(f'y = {y}')
test(x = 10,y = 20)
test(y = 111,x = 222)
'''
x = 10
y = 20
x = 222
y = 111
'''