目录
- 函数返回值
- 文档字符串和help()
- 函数的作用域
- 命名空间
- 递归函数
1. 函数返回值
返回值就是函数执行以后返回的结果
通过return来指定函数的返回值
return后面可以跟任意且不限于一个的对象,返回值甚至可以是一个函数
# 求任意数的和
def fn(*nums):
result = 0
for n in nums:
result += n
# print(result)
return result
print('我不会执行')
r = fn(1,2)
-
在函数中 return后面的代码都不会执行,return一旦执行函数自动结束
-
注意调用函数和函数对象的区别
def fn1():
return 100
print(fn1)
print(fn1())
-
fn1和fn1()的区别:
fn1是函数对象
fn1()是在调用函数
2. 文档字符串和help()
- help()是Python中内置函数,通过help()函数可以查询Python中函数的用法
可以试着打印help(print)
,即可查看print()
函数的更多神奇操作。 - 在定义函数时,可以在函数内部编写文档字符串(三个引号包围的字符串),文档字符串就是对函数的说明
# 自定义函数
def fn(a, b, c):
"""
这个函数式一个文档字符串的实例
参数
a:作用 类型 默认值......
b:作用 类型 默认值......
c:作用 类型 默认值......
"""
return 100
help(fn)
- 函数的作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
所以作用域指的就是变量生效的区域
- Python的作用域一共有4种,分别是:
• L(local):局部作用域,即函数中定义的变量;
• E(enclosing):嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
• G(global):全局变量,就是模块级别定义的变量;
• B(build-in):内建作用域,系统固定模块里面的变量,比如:int()等;
简单介绍两种:
- 全局作用域
• 全局作用域在程序执行时创建,在程序执行结束时销毁
• 所有函数以外的区域都是全局作用域
• 在全局作用域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进行访问 - 函数作用域
• 函数作用域在函数调用时创建,在调用结束时销毁
• 函数每调用一次就会产生一个新的函数作用域
• 在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问 - 函数作用域优先级
局部作用域(L)>父级函数作用域(E)>全局作用域(G)>系统模块(B)
注意:
• 如果在函数中修改全局变量,那么就需要使用global
进行声明,否则出错
• 如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,小技巧强龙不压地头蛇
global
的本质:
1.在函数中不使用global声明全局变量时不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据。
2.对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global时无法修改全局变量。
3.对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可修改全局变量。
4. 命名空间
命名空间实际上就是一个字典,是一个专门用来存储变量的字典
locals()用来获取当前作用域的命名空间
如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间
返回值是一个字典
a = 20
def fn3():
global a
a = 50
print('函数内部:','a =',a)
s = locals()
print(s)
print(a)
print(s['a'])
5. 递归函数
递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题
- 递归式函数有2个条件
1.基线条件 问题可以被分解为最小问题,当满足基线条件时,递归就不执行了
2.递归条件 可以将问题继续分解的条件
递归简单理解就是自己去引用自己
递归式函数即在函数中自己调用自己
无穷递归 类似于死循环
- eg:用递归的方式求任意数的阶乘
# 用递归的方式求任意数的阶乘
# 10!= 10 * 9!
# 9! = 9 * 8!
# 8! = 8 * 7!
# ....
# 1! = 1
def fn2(n):
# 参数 n要求阶乘的数字
# 1.基线条件
if n == 1:
# 1的阶乘就是1 直接返回结果
return 1
# 2.递归条件
return n * fn2(n-1)
print(fn2(10))
- Q.思考一下,按照递归的特性,在编程中有没有不得不使用递归的情况?
A:有。例如汉诺塔,目录索引(因为你永远不知道这个目录里边是否还有目录) , 快速排序(二十世纪十大算法之一),树结构的定义等如果使用递归,会事半功倍,否则会导致程序无法实现或相当难以理解。
网友评论