- 参考书《Python基础教程(第三版)》—— Magnus Lie Hetland
文章目录
- 一、自定义函数
- 1. 判断某个对象x可否作为函数调用
- 2. 自定义函数
- 二、函数参数
- 1. 修改参数
- 2. 传参数和传返回值的本质
- 3. 参数缺省值和关键字参数
- 4. 收集参数
- 5. 分配参数
- 三、作用域(命名空间)
- 1. 什么是作用域
- 2. 在函数内访问全局变量
- (1)读全局变量
- (2)写全局变量
- 3. 作用域嵌套
一、自定义函数
1. 判断某个对象x可否作为函数调用
- 内置函数
callable(object):bool
:返回一个bool值,代表x是不是可被调用的对象
2. 自定义函数
- 格式:
- 其实不是函数的函数
- 数学意义上的函数总是返回根据参数计算的结果
- 在python中,有些函数什么也不返回,这种函数可能无return语句,或者有return但无返回值(这样可以提前结束函数)
- 在有些语言中,这种称作 “过程”,在python中也叫 “函数”
- 对于不显式写出返回值的函数,python自动返回None
- 简单说:所有函数都有返回值,如果没有指定就返回
None
- 示例
- 给函数编写文档
- 在定义函数的def语句后一行,立即用
'...'
形式写一个注释,这称为文档字符串,这个字符串会被作为函数的一部分储存起来 - 像这样调用
函数名.__doc__
,返回一个字符串(注意这里前后都是两个下划线) -
help(函数名)
在交互式解释器中获取有关函数的信息
二、函数参数
1. 修改参数
- 字符串、数、元组是不可变的,操作形参不会影响实参(对于这些类型来说,传参过程如赋值n = name,实际新建了一个值相同的对象并用形参指向它)。
- 这种情况下,函数中无法对实参产生影响,如果一定要通过函数修改实参,只有一种妥协的方法:把形参经处理后得到的值作为返回值,在返回后对实参重新赋值
- 列表、字典等是可变的,操作形参会影响实参(对于这些类型来说,传参过程如赋值n = name,直接用形参指向实参对象,并没有新建对象)。如果希望函数内操作形参不影响实参,必须创建列表/字典的副本
2. 传参数和传返回值的本质
- 假如函数形参n,调用时写入实参name,传参过程可以看作:n = name
- 如果参数是不可变对象如字符串、数、元组:进行值传递,可以理解为根据实参数值创建了相等的对象(不是相同对象)传入函数,实参本身不会受到函数内操作的任何影响。(事实上,仅仅传参数这一步还是传的引用(地址值),但对形参进行赋值时就会创建新对象了)
- 如果参数是可变对象如列表、字典等:进行引用传递,相当于让形参n引用实参name,没有创建新对象,实参会受到函数内操作的影响。(本质是也是传值,不过传的是地址值)
- python函数和方法的返回值的方法和传参数的方法相同,也是值传递/引用传递(地址值传递)
3. 参数缺省值和关键字参数
- 类似C++,定义函数时可以给参数加上缺省值
- 关键字参数:调用函数时,可以指出形参,这样实参就不用按顺序写了
4. 收集参数
- 定义函数时利用
*
在函数中用形参收集多个非关键字参数为列表 - 定义函数时利用
**
在函数中用形参收集多个关键字参数为字典 - 两种收集参数方法(
*
和**
)还有普通定义参数方法可以混合使用 - 详见:Python 中函数的 收集参数 机制
5. 分配参数
- 调用函数可以用
*
把列表作为非关键字参数函数的形参,在函数内部会自动序列解包 - 调用函数可以用
**
把元组作为关键字参数函数的形参,在函数内部会自动序列解包 - 不要同时使用 “收集参数” 和 “分配参数” 这样做和不加*没有区别
- 两种分配参数方法(*和**)还有普通写实参的方法可以混合使用
三、作用域(命名空间)
1. 什么是作用域
- 变量可以看作“指向值的名称”,执行x=1,名称x指向1,这几乎和字典一样
- 作用域可以看作 “看不见的字典” ,用
vars()
可以返回这个 “看不见的字典”
- 注意:不应修改
vars()
返回的字典,这样的结果是不确定的 - 除全局作用域外,每次函数调用都创建一个作用域
2. 在函数内访问全局变量
(1)读全局变量
- 通常在函数内读取全局变量值没有问题
- 但如果函数有局部变量和全部变量同名,全局变量将被 “遮盖”
- 可以用
globals()
函数帮忙,这个函数类似vars()
,返回一个包含全局变量的字典(不同于vars()是返回的“看不见的字典”,这是明确的所有全局变量的字典) - 相应的,有
locals()
返回一个包含局部变量的字典
(2)写全局变量
- 在函数内部给变量赋值时,此变量默认为局部变量
- 用
global
修饰符指出变量是全局的
3. 作用域嵌套
- python允许函数嵌套定义,外面的函数可以返回里面的函数(不是调用)。关键在于,这个返回的函数内部可以访问其定义所在的作用域(即这里的
multiplier
函数作用域)
- 常利用这种方法,用一个函数创建另一个函数
- 像
multiplyByFactor
这样存储其所在作用域的函数称为 “闭包” - 通常不能给外部作用域内的变量赋值,如果一定要这样做可以用关键字
nonlocal
,类似global
用法