python函数【二】:自定义函数

前言

python中函数是一等对象,地位非常重要,类定义中的类方法、静态方法、实例方法本质就是函数。本部分主要记录自定义函数,自定义函数有两种类型,一种是lambda表达式(lambda 参数列表: 表达式 ;lambda表达式本质是匿名函数,匿名函数是指没有为函数对象绑定函数名称,其参数就是参数列表,返回值就是表达式的值)。

另一种是def语句,重点是def语句,需要理解def语句中的参数、调用、返回值、以及函数的属性。
 

def语句

def function_name(*args, **kwargs):
	""" document string """
	function_body
	return [expression]

执行|编译

函数的定义体是一组可执行语句(executable statement),当编译函数体后,会生成函数对象,函数对象中封装了函数体的定义逻辑,并将函数名称绑定到函数对象上。

当函数被调用时,函数对象会自动引用调用处的全局命名空间(global namespace),正式由于对调用处全局命名空间的引用,函数对象才能识别函数对象外的变量。对调用处全局空间的引用应该是依赖__global__属性。注意函数定义并不执行函数体,只有当函数被调用时才会执行函数体。

另外在函数定义中,可以在def语句之前添加“装饰器表达式”,对于装饰器语法糖可参考Python装饰器语法部分。
 

参数

关于函数的参数列表,首先需要区分几组概念:

1)“形式参数”是指函数定义时的参数名统称,可以将形式参数理解为占位符号;“实际参数”是指函数调用时,传入函数的实际值。

2)函数定义时,支持为形式参数指定默认值。当函数调用时,如果不提供实际参数值,则对应的形式参数就采取默认值。默认值会在函数编译后写入函数对象的__defaults__属性中。注意函数定义中,形式参数名=默认值,对应的形式参数不一定是关键词参数。注意区分该种定义形式与函数调用时关键词参数的区别。

3)“位置参数”、“关键词参数”是在函数调用层面的概念,当以key=value形式传递参数,对应的形式参数又称为“关键词参数”。在关键词参数中,有一种特殊情况,就是“仅关键词参数”,其意义是传递实参给形参时,必须以key=value的形式传递。

知道形参与实参的区别、以及位置参数与关键词参数的区别后,在函数定义中还需要注意“是否为形参设置单星号”,用于收集任意个实参值,“是否为形参设置双星号”,收集任意个关键字参数。带星号、双星号的形式参数,星号、双星号并非形式参数名的一部分,在函数定义体内,直接使用星号、双星号后面的标识符就可以。另外星号标识的形式参数,在函数被调用时,会初始化为一个空元组,双星号标识的形式参数在函数被调用时,初始化为一个字典。

形式参数、函数返回值可以定义标注信息(annotation),标注信息作为函数的元数据,不参与任何计算,定义的标注信息存储在函数的__annotation__属性中。为形式参数添加标注信息的方式为arg: expression = expression,即使用冒号加一个表达式;为函数返回值添加标注信息的方式为,在参数列表与冒号之间添加-> expression。另外需要注意,参数与返回值的标注信息,在函数编译后就写入__annotation__属性,与函数文档字符串写进__doc__、默认值写入__defaults__类似,并非是在函数被调用时才写入。
 

调用

调用函数时,函数对象做的第一件事就是为所有形式参数赋值,只有当参数列表完全解析正确,才会执行函数体中的逻辑并返回值。关于参数列表的解析,即将实际参数值赋值给位置参数,需要了解位置参数、仅关键词参数、关键词参数的概念及区别。1)位置参数是指实际参数值传入函数的位置,没有标识符标识其属于哪个形式参数,该位置参数将传递给对应位置的形式参数;2)仅关键词参数是后来加入的特征,当参数列表中包含带单星号、双星号的形式参数时,夹在单星号形式参数与双星号形式参数之间的参数,必须以关键字的形式传递,否则其值就会被单星号形式参数、或者双星号形式参数收集;3)关键词参数,是指以key=value的形式传递参数值,其中的key就是函数定义参数列表中的参数名,value值将赋值给名为key的形式参数。

形式参数的解析顺序如下:1)为位置参数赋值,2)为关键词参数赋值,包括仅关键字参数与关键字参数;3)如果还有形式参数没有赋值,则取函数定义中的默认值,如果默认值都被取完,还有形式参数未被赋值,则抛出TypeError。根据参数解析顺序,在函数定义中,关键词参数一定要定义在位置参数后面,否则会产生语法错误
 

在这里插入图片描述
函数调用中的参数解析还支持“解包技术”,*expression或者**expression,其中*expression中的表达式必须为可迭代对象, **expression中的表达式必须为mapping对象。

当调用函数时传入*expression、**expression,形式参数解析顺序不变,但要注意:1)*expression会提取出可迭代对象中的所有元素,按照传入顺序作为位置参数,*expression会在**expression、关键词参数之前被解析,即使它被后传入。2)**expression会解包关键词参数,如解析出来的关键词已经存在了,则会抛出TypeError。
在这里插入图片描述
在这里插入图片描述

返回值

除了函数体执行时抛出异常,否则函数总是会返回值,若不指定return子句,则返回None,最好指定return子句,即便是返回None。函数体执行return子句后就会停止,即便后面还有代码未执行,另外一个函数体内可以包含多条return子句
 

属性

在这里插入图片描述
在这里插入图片描述

属性含义读写类型
__code__code对象,表示编译的函数体writable
__globals__对字典的引用,该字典包含函数定义模块中的全局变量readable
__dict__一个命名空间,包含函数对象的任意属性 writable
__closure__包含函数的绑定的自由变量writable

 

参考资料

1. Compound statements-- Function defination

2. Expression–calls

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值