1 函数的返回值
# 求任意数的和
def fn(*nums):
result = 0
for n in nums:
result += n
# print(result)
return result
r = fn(5,6)
print(r)
结果
11
-
返回值就是函数执行以后返回的结果
-
用return来指定函数的返回值
def fn():
return 100
r = fn()
print(r)
print(fn())
100
100
-
我们可以直接使用函数的返回值也可以通过变量来接收函数的返回值
-
return后面可以跟任意对象,甚至可以是一个函数
def fn():
# return 100
# return 'python'
# return [1,2,3]
return {'name':'张三'}
r = fn()
print(r)
print(fn())
{'name': '张三'}
{'name': '张三'}
def fn():
# return 100
# return 'python'
# return [1,2,3]
# return {'name':'张三'}
def fn2():
print('hello')
return fn2
r = fn()
# r()
print(r)
结果
<function fn.<locals>.fn2 at 0x00000161F5A35620>
def fn():
def fn2():
print('hello')
return fn2
r = fn()
r()
hello
结果
- 如果仅仅写一个return或者不写return则相当于return none
def fn3():
print('hello')
r = fn3()
print(r)
结果
hello
None
- 在函数中,return后面的代码不会执行,return一旦执行函数自动结束
def fn3():
print('hello')
return
print('123')
r = fn3()
结果
hello
- return、break、continue的区别:
break退出当前循环
def fn4():
for i in range(5):
if i == 3:
break
print(i)
print('循环执行完毕')
fn4()
结果
0
1
2
循环执行完毕
continue跳过本次循环
def fn4():
for i in range(5):
if i == 3:
# break
# return
continue
print(i)
print('循环执行完毕')
fn4()
结果
0
1
2
4
循环执行完毕
return可以用结束函数
def fn4():
for i in range(5):
if i == 3:
# break
return
print(i)
print('循环执行完毕')
fn4()
结果
0
1
2
- 函数加括号和不加括号
fn5是函数对象, 如果你希望把函数对象直接给他,那就不加()
fn5()是在调用函数,如果紧紧你需要的是返回值,那就加上()
def fn5():
return 100
# fn5和fn5()的区别
# fn5是函数对象, 如果你希望把函数对象直接给他,那就不加()
# fn5()是在调用函数,如果紧紧你需要的是返回值,那就加上()
print(fn5) # <function fn5 at 0x0000015125662EA0>
print(fn5()) # 100
结果
<function fn5 at 0x0000015125662EA0>
100
2 文档字符串
- help()函数:可以查询其他函数的用法
help(函数对象)
def fn(a:bool,b:int,c:str)->int:
'''
这个函数是一个文档字符串的实例
参数
a:作用 类型 默认值……
b:作用 类型 默认值……
c:作用 类型 默认值……
'''
return 100
help(fn)
结果
Help on function fn in module __main__:
fn(a:bool, b:int, c:str) -> int
这个函数是一个文档字符串的实例
参数
a:作用 类型 默认值……
b:作用 类型 默认值……
c:作用 类型 默认值……
3 函数的作用域
- 作用域指的就是变量生效的区域
- Python中有两种作用域
- 全局作用域:
全局作用域在程序执行时创建,在程序执行结束时销毁,所有函数以外的部分都是全局作用域,在全局作用域中定义的变量都属于全局变量,全局变量可以在程序的任意位置访问 - 函数作用域:
函数作用域在函数调用时创建,在调用结束后销毁,函数每调用一次就会产生一个新的作用域,在函数作用域中定义的变量都是局部变量,它只能在函数内部被访问到
b = 50
def fn():
# a定义在了函数内部,所以他的作用域就是函数内部,函数外部是无法访问的
a = 10
print('函数内部:','a =',a)
print('函数内部:', 'b =', b)
fn()
print('函数外部:','b =',b)
函数内部: a = 10
函数内部: b = 50
函数外部: b = 50
def fn2():
a = 30
def fn3():
# global a # 声明在函数内部的使用,
a = 40
print('这是fn3内部','a =',a)
fn3()
print('这是函数外部','a =',a)
fn2()
这是fn3内部 a = 40
这是函数外部 a = 30
- global关键字
如果希望在函数内部修改全局变量,则使用global关键字,来声明内部的变量为全局变量
a = 30
def fn3():
# 如果希望在函数内部修改全局变量,则使用global关键字,来声明内部的变量为全局变量
# 声明在函数内部使用的变量a是全局变量,则此时在去修改a时,就是在修改全局变量
global a
a = 40
print('这是fn3内部','a =',a)
fn3()
print('这是函数外部','a =',a)
这是fn3内部 a = 40
这是函数外部 a = 40
4 命名空间
-
命名空间:实际上就是一个字典,是一个专门用来存储变量的字典
-
locals():用来获取当前作用域的命名空间
-
如果在全局作用域中调用locals()则获取的是全局命名空间,如果在函数作用域中调用,则获取的是函数的命名空间 返回是一个字典
-
在外部时
# 命名空间
a = 30
def fn3():
global a
a = 40
print('这是fn3内部','a =',a)
s = locals()
print(a)
print(s['a'])
s['c'] = 100 # 在命名空间添加了键值对
print(c)
结果
30
30
100
- 在内部时
def fn4():
a = 10
s = locals() # 获取函数内部的命名空间
print(s)
fn4()
结果
{'a': 10}
def fn4():
a = 10
s = locals() # 获取函数内部的命名空间
s['b'] = 20
print(s)
fn4()
结果
{'a': 10, 'b': 20}
- globals():函数可以用来在任意位置获取全局命名空间
获取
a = 30
def fn3():
global a
a = 40
print('这是fn3内部','a =',a)
s = locals()
def fn4():
a = globals()
# a['a'] = 10 # 可以修改全局变量
print(a)
fn4()
print(a)
结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000020FDA78D240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Users/RAZER/PycharmProjects/lect10/命名空间.py', '__cached__': None, 'a': 30, 'fn3': <function fn3 at 0x0000020FDA732EA0>, 's': {...}, 'fn4': <function fn4 at 0x0000020FDC5B5620>}
30
然后 获取后修改
a = 30
def fn3():
global a
a = 40
print('这是fn3内部','a =',a)
s = locals()
def fn4():
a = globals()
a['a'] = 10 # 可以修改全局变量
print(a)
fn4()
print(a)
结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002A9BF5DD240>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Users/RAZER/PycharmProjects/lect10/命名空间.py', '__cached__': None, 'a': 10, 'fn3': <function fn3 at 0x000002A9BF4D2EA0>, 's': {...}, 'fn4': <function fn4 at 0x000002A9BF845620>}
10
5 递归
练习
- 尝试求10的阶乘(10!)
1! = 1
2! = 12 = 2
3! = 123 = 6
…89*10 =
# 创建变量 10
n = 10
for i in range(1,10):
n *= i
print(n)
结果
3628800
- 求任意数的阶乘 来个函数
# 求任意数的阶乘 来个函数
def fn1(n): # 确立形参
# 参数 n
# n = 10
# 定义一个变量保存结果
result = n
for i in range(1,n):
result *= i
return result
print(fn1(10)) # 传入实参
结果
3628800
5.1 递归式的函数
- 递归简单理解就是自己调用自己
递归式函数,在函数中自己调用自己 - 无穷递归–死循环
def fn():
fn()
fn()
- 递归是解决问题的⼀种⽅式,它的整体思想,是将⼀个⼤问题分解为⼀个个的⼩问题,直到问题⽆法分解时,在去解决问题
递归式函数有2个条件
- 基线条件 问题可以被分解为最⼩问题,当满⾜基线条件时,递归就不
执⾏了 - 递归条件 可以将问题继续分解的条件
- 用递归的方式求任意数的阶乘
# 用递归的方式求任意数的阶乘
# 分析 10! = 10 * 9!
# 9! = 9 * 8!
# ....
# 1! = 1
def fn2(n):
# 参数 n要求阶乘的数字
# 基线条件
if n==1:
# 1的阶乘就是1 直接返回结果
return 1
# 递归条件
return n * fn2(n-1)
print(fn2(10))
结果
3628800
6 递归的练习
练习1
- 创建一个函数来为任意数字做任意幂运算
分析106 =10 * 105
def fn(n,i): # n是任意数,i是任意幂
# 基线条件
if i == 1:
return n
# 递归条件
return n * fn(n,i-1)
print(fn(3,4))
print(3**4)
结果
81
81
练习2
创建一个函数,用来检测任意字符串是否是回文字符串,如果是返回True
回文字符串–从前往后念和从后往前念是一样的,,例如abcba
- abcdefgfedcba
分析–先检查第一个字符和最后一个字符是否一致,如果不一致一定不是回文字符串
如果一致就要检查剩余的部分bcdefgfedcb是不是回文字符串
以此类推
最后检查的是g
方法1
def fn2(s):
# 参数s是我们要检测的字符串
# 基线条件
# 字符串的长度小于2 则字符串一定是回文
if len(s)<2:
return True
# 第一个字符和最后一个字符不相同 则一定不是回文
elif s[0] != s[-1]:
return False
# 递归条件
return fn2(s[1:-1]) # 切片
print(fn2('abcdefgfedcba'))
结果
True
方法2
def fn2(s):
# 参数s是我们要检测的字符串
# 基线条件
# 字符串的长度小于2 则字符串一定是回文
if len(s)<2:
return True
# 第一个字符和最后一个字符不相同 则一定不是回文
elif s[0] != s[-1]:
return False
else:
return fn2(s[1:-1])
# # 递归条件
# return fn2(s[1:-1]) # 切片
print(fn2('a'))
结果
True