1.函数简介
- 函数也是一个对象(对象是内存中专门用来存储数据的一块区域)
- 函数可执行代码,也可以调用
语法
def 函数名([形参1,形参2,形参3....]):
代码块
【注意】:
- 函数名必须符合标识符的规范(可以包含字母、数字、下划线但是不能以数字开头)
- 区别一下函数对象与函数调用:print是函数对象 , print()是调用函数
2.函数的参数
2.1 形参和实参
- 形参(形式参数): 定义形参就相当于在函数内部声明了变量,但是并不是赋值
- 实参(实际参数):指定了形参,那么在调用函数时必须传递实参,实参将会赋值给对应的形参,简单来说有几个形参就要有几个实参
# 定义一个函数 任意两个数的和
# 函数的参数
# 在定义函数的时候,可以在函数后面的括号中定义数量不等的形参
# 多个形参之间要用 ,隔开
# 简单来说你有几个形参就要赋值几个实参
def s(a,b):
# print(4 + 5)
# a = None
# b = None
# print(a + b)
print(a ,'+',b,'=',a+b)
s(8,6)
2.2 函数的传递方式
1.定义形参时,可以为形参指定默认值,指定了默认值以后,如果用户传递了参数则默认值不会生效,如果用户没有传递,则默认值就会生效。
2.位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参(一对一关系赋值)。
3.关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递(a对a,b对b)。
4.混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去。
# 在定义函数的形参的时候,可以指定一个默认值
# def fn(a,b,c = 20):
#
# print('a =',a)
# print('b =',b)
# print('c =',c)
# fn(1,2,3)
# fn(1,2)
# 函数的传递方式:
# 位置传参
# 关键字传参
# 关键字传参可以不按照定义的顺序来传递,它是根据参数的名字来传递
# def fn(b=1,c=2,a=3):
#
# print('a =',a)
# print('b =',b)
# print('c =',c)
# fn()
2.3 不定长参数
- 定义函数时,可以在形参前面加一个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到一个元组中。
- 带*号的形参只能有一个,可以和其他参数配合使用。
- *形参只能接受位置参数,不能接受关键字参数
- **形参可以接收其他的关键字参数,它会将这些参数统一保存到字典当中,字典的key就是参数的名字,字典的value就是参数的值。
- **形参只有一个,并且必须写在所有参数的后面
# 定义一个函数 来求任意数的和
# def s(a,b,c):
#
# print(a + b + c)
#
# s(1,2)
# TypeError: s() takes 2 positional arguments but 3 were given
def s(*a):
# 定义一个变量来保存结果
r = 0
# 遍历元祖,并将元祖中的数进行相加
for n in a:
r += n
print(r)
s(1,2,5)
# def fn2(a,b,*c):
#
# print('a =',a)
# print('b =',b)
# print('c =',c)
#
# fn2(1,2,3,4,5)
# def fn2(a,*b,c):
#
# print('a =',a)
# print('b =',b)
# print('c =',c)
#
# fn2(1,2,3,4,c=5)
# def fn3(b,c,**a):
#
# print('a =',a)
# print('b =', b)
# print('c =', c)
#
# fn3(b=1,d=2,c=3,e=20,f=30)
# *a处理的是位置参数 **a是处理的是关键字参数
3.函数的返回值
1.返回值就是函数执行以后返回的结果
2.通过return来指定函数的返回值
3.return后面可以跟任意对象,也可以是一个函数
4.文档字符串
- help()是Python中内置函数,通过help()函数可以查询Python中函数的用法
- 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是对函数的说明(类似注释,其实也是注释)
def fn():
'''
help()
通过help()函数可以查询其他函数的用法
语法: help(函数对象)
'''
help(fn)
5.函数的作用域
-
作用域指的是变量生效的区域
-
在Python中一共有两种作用域:
全局作用域: 1.全局作用域在程序执行时创建,在程序结束时销毁 2.所有函数以外的区域都是全局作用域 3.在全局作用域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进行访问 函数作用域: • 函数作用域在函数调用时创建,在调用结束时销毁 • 函数每调用一次就会产生一个新的函数作用域 • 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问
# b = 20
# def fn():
# a = 10 # a定义在了函数的内部,所以他的作用域就是函数的内部,函数外部是无法访问的
# print('函数内部:','a =',a)
# print('函数内部:', 'b =', b)
# fn()
# print('函数外部:','b =',b) # NameError: name 'a' is not defined
# def fn2():
# a = 30
# def fn3():
# # a = 40
# print('fn3中 a =',a)
# return fn3()
# fn2()
# a = 20
# print('函数外部 a = ',a)
# def fn3():
# # 如果希望在函数内部修改全局变量,则需要使用一个关键字global,来声明变量
# global a
# a = 100
# print('函数内部 a =',a)
# fn3()
# print('函数外部!!!! a = ',a)
6.命名空间
1.命名空间实际上就是一个字典,是一个专门用来存储变量的字典
2.locals()用来获取当前作用域的命名空间
3.如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间
4.返回值是一个字典
7.递归函数
-
递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题
-
递归式函数有2个条件:
1. 基线条件: 问题可以被分解为最小问题,当满足基线条件时,递归就不执行了 2. 递归条件 :可以将问题继续分解的条件
# 定义一个函数 求任意数的阶乘
def fn(n):
# 参数n: 要求阶乘的数字
# 定义一个变量来保存结果
r = n
for i in range(1,n):
r *= i
return r
fn()
# 定义一个函数 来为任意数字做任意幂运算 n ** i
def fn4(n,i):
# 参数 n 做幂运算的数字 i 做幂运算的次数
# 1.基线条件
if i == 1:
# 求1次幂
return n
# 2.递归条件 10 * 10 ** 3
return n * fn4(n,i-1) # 10 ** 3
print(5 ** 3)
print(fn4(5,3))
8.高阶函数
高阶函数有2个特点符合任意的一个特点即是高阶函数:
1 接收一个或多个函数作为参数
2 将函数作为返回值返回的也是个高阶函数
def fn2(i):
if i % 2 == 0:
return True
def fn3(i):
if i > 5:
return True
return False
def fn4(i):
if i % 3 == 0:
return True
return False
# 定义一个函数
# 可以指定一个列表中的所有的偶数,保存到一个新的列表
def fn(func,l):
# 参数 l 就是被指定的列表 func
# 创建一个新的列表
new_lst = []
for n in l:
# 判断n的奇偶
if func(n):
new_lst.append(n)
return new_lst
print(fn(fn2,lst)) # 求偶数
8.1 闭包
1.闭包的好处
1.通过闭包可以创建一些只有当前函数能访问的变量
2.可以将一些私有数据藏到闭包中
2.行成闭包的条件
1.函数嵌套
2.将内部函数作为返回值返回
3.内部函数必须要使用到外部函数的变量
# 高阶函数的第二种,将函数作为参数返回
# 这种高阶函数我们称之为闭包
# 通过闭包可以创建一些只有当前函数能够访问的变量
# 可以将一些私有的重要的放到闭包当中
def fn():
a = 10
# 在函数内部在定义一个函数
def fn2():
print('我是fn2',a)
# 将内部函数fn2作为返回值返回
return fn2
r = fn()