首页 > 技术文章 > 函数

mayu-huangdi 2021-11-12 19:55 原文

函数的语法结构

def 函数名(参数1,参数2):
	'''函数注释'''
	函数体
	return 返回值
  1. def:定义函数的关键字
  2. 函数名:函数名相当于变量,绑定函数体代码所在的内存地址
  3. 参数:函数调用所需要传入的数据,可以没有参数
  4. 函数注释:函数说明即使用方法
  5. 函数体:函数执行的代码
  6. 返回值:函数执行完返回的数据,可以没有返回值,默认为None

函数的定义与调用

  • 函数必须先定义在调用
  • 函数定义阶段只检测语法结构不执行代码
  • 函数在调用阶段执行代码
  • 函数名()调用函数,有需要参数传入参数

函数的分类

  1. 内置函数
    python解释器自带生成的函数。如,len()等。
  2. 自定义函数
    1. 无参函数
      函数定义阶段没有设置参数
      def my_function1():
      print('无参函数')
    2. 有参函数
      函数定义阶段设置了参数
      def my_function2(param):
      print(param)
    3. 空函数
      函数体代码为pass
      def my_function3():
      pass

函数参数两大分类

  1. 形参
    函数定义阶段括号内定义的变量就是形式参数(形参)。
  2. 实参
    函数调用阶段括号内传入的值就是实际参数(实参),实参可能是变量,值,函数返回值等。

位置参数

# 下述定义的函数中param1,param2,param3在函数定义阶段按照顺序排列,
# 在调用函数时必须按照定义的顺序传入值,传参不能少也不能多。
def func(param1,param2,param3):
	pass

# 关键字传参不需要注意传参顺序
func(param3=1,param1=2,param2=1)

默认参数

# 下述中func函数参数param在定义时设定了默认值
def func(param = 1):
	print(param)
# 默认参数在函数调用时,如果未传入参数那么使用默认设置的值,传入参数则使用传入的值
func()  # 1
func(2)  #2

#特别的,默认参数必须放在位置参数后面,简单在前,复杂在后

可变长参数

# 使用*变量名表示函数的可变长参数。
# *arg接收除位置参数外多余的传入值作为元组传入。
def func(param,*args):
	print(param,args)
# 打印位置参数传入的1,args接收2,3,4作为元组
func(1,2,3,4)  # 1 (2,3,4)
# 位置参数后的值可以传入列表或元组,通过*变量名传入。
list = [2,3,4]
func(1,*list)  # 1 (2,3,4)

# 使用**变量名也可以表示可变长参数。
# **kwargs接收关键字传参作为字典传入。
def func2(**kwargs):
	print(kwargs)
# 关键字传参通过参数名=参数值形式传入
func2(name='xie',age=8)  # {'name':'xie','age':18}
# 关键字传参可以通过**字典变量名传入
dic = {'name':'xie','age':18}
func2(**dic)  # {'name':'xie','age':18}

# 可接收任意参数函数
func3(*args,**kwargs):
	print(args,kwargs)

名称空间

  1. 什么是名称空间
    存放变量名和变量值绑定关系的地方(类似民政局)
  2. 名称空间分类
    1. 内置名称空间
      python解释器提前声明的,如len()、print()可直接使用
    2. 全局名称空间
      py文件中顶格编写的代码都存入全局名称空间
    3. 局部名称空间
      函数体代码执行时产生的就是局部名称空间
  3. 存活周期
  • 内置名称空间随python解释器启动与关闭而创建与销毁
  • 全局名称空间与py文件运行与结束而创建与销毁
  • 局部名称空间随函数执行与结束而创建与销毁
  1. 名称查找顺序
# 确定当前代码执行的环境,在哪个名称空间下就在当前名称空间查找。
x= n = 1
def func():
	n = 2
	print(n)

func()  # 2

# 如果当前空间下没找到相应的变量名则找上层的名称空间。
def func2():
	print(n)

func2()  # 1

# 函数在定义阶段已经决定在哪儿个名称空间中查找
# 以下函数从局部名称空间中查找x,但是报错x未定义就使用
def func3():
	print(x)
	x = 27

func3()  # 报错
  1. 名称空间作用域
    不同名称空间影响的范围不同。
    内置名称空间:程序执行阶段任何时间地方都能使用。
    全局名称空间:程序执行阶段任何时间地方都能使用。
    局部名称空间:一般在各自的局部空间中才能使用。
# global能够将局部作用域变量转化成全局中的变量
n = 1
def func():
	global n
	n = 2

func()
print(n)  # 2

# nonlocal能够将当前局部作用域中的变量转化成上层局部作用域中的变量
def func2():
	n = 1
	def func3():
		nonlocal n
		n = 2
	func3()
	print(n)

func2()  # 2

函数对象(函数名)

# 函数可以作为参数传入,通过变量名()调用
def func(a):
	print(a)
	a()

def func2():
	print('hello world')

func(func2)
# <function func2 at 0x000002520F34F2F0>
# hello world

#函数可以作为变量名赋值
def func3():
	print('hello')

a = func3
a()  # hello

#函数可以作为返回值
def index():
	print('index')

def func4():
	print('func4')
	return index

a = func4()  # func4
a()  # index

#函数可以作为容器类数据的元素
def func5():
	print('func5')

func_dict = {'1',func5}
a = func_dict.get('1')
a()  # func5

闭包函数

定义外层函数在其内部定义另一个函数,返回内层函数,通过此函数访问外层函数中数据,那么这样的函数称为闭包函数。

# 调用outter返回func函数名赋值于a,a()打印了1,返回的函数访问了outter中定义的变量n
def outter():
	n = 1
	def func():
		print(n)
	return func

a = outter()
a()  # 1

# 调用outter函数传入1返回函数名赋值于a,a()打印了1,返回的函数访问了outter函数的传入实参1
def outter(n):
	def index():
		print(n)
	return index

a = outter(1)
a()  # 1

推荐阅读