函数(2)
1.1 函数的返回值
1 返回值就是函数执行以后返回的结果
2 fn和fn()的区别
print(fn) # fn是函数对象 打印fn就是在打印函数对象
print(fn()) # fn()是在调用函数 打印fn()实际上是在打印fn()函数的返回值
求任意数的和
def s(*nums):
# 定义一个变量来保存结果
result = 0
# 遍历元组,并将元组当中的元素进行累加
for n in nums:
result += n
print(result)
return result
r = s(1,2,3,4) # 将返回值result赋值到r
print(r+6)
运行结果
10 # r = result
16 # 将返回值赋值给其他的变量后,就可以进行调用
3 用return来指定函数的返回值
我们可以直接使用函数的返回值也可以通过变量来接收函数的返回值
return后面可以跟任意对象,甚至可以是一个函数
def fn():
def fn2():
print('hello')
return fn2 #fn()函数的返回值为fn2
r = fn() # 这个函数执行的结果就是返回值的结果,r = fn2
r() # 执行fn2()
print(r) # 打印fn()的对象
print(fn()) # 打印fn2的对象
运行结果
hello
<function fn.<locals>.fn2 at 0x000001F4BFC91EA0>
<function fn.<locals>.fn2 at 0x000001F4BFC91F28>
4 如果仅仅写一个return或者不写return则相当于return none
def fn2():
a = 10
r = fn2()
print(r)
运行结果
None
5 在函数中,return后面的代码不会执行,return一旦执行函数自动结束
下面举两个例子
一:
def fn3():
print('python')
return
print('java')
r = fn3()
print(r)
运行结果
python #只运行了第一条的rint()语句
None # 遇见return返回值后就不再执行print('java')语句
二:
def fn4():
for i in range(5):
if i == 3:
# break # break退出当前循环
# continue # continue跳过本次循环
return # return可以用结束函数
print(i)
print('循环执行完毕')
fn4()
运行结果
0
1
2 # 当i = 3时执行return语句,结束函数
1.2文档字符串
1 help()函数 可以查询其他函数的用法
语法 help(函数对象)
help(print)
运行结果
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
2 也可以自己设置
def fn(a:int,b:str,c:bool)-> int:
#int,strr,bool存在不起任何作用,只是提示使用者对应的数据类型,最后一个int 说明此函数返回值为整数型
'''
# 也可自己在后面设置a,b,c的数据类型,以及返回值类型
:param a: 类型 int 默认值...
:param b: 类型 str 默认值...
:param c: 类型 bool 默认值...
:return: int
'''
return 1
help(fn)
运行结果
fn(a:int, b:str, c:bool) -> int
#也可自己在后面设置a,b,c的数据类型,以及返回值类型
:param a: 类型 int 默认值...
:param b: 类型 str 默认值...
:param c: 类型 bool 默认值...
:return: int
1.3 函数的作用域
一 作用域指的就是变量生效的区域
全局作用域
1 全局作用域在程序执行时创建,在程序执行结束时销毁
所有函数以外的部分都是全局作用域
2 在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置访问
函数作用域
1 函数作用域在函数调用时创建,在调用结束后销毁
2 函数每调用一次就会产生一个新的作用域
在函数作用域中定义的变量都是局部变量,它只能在函数内部被访问到
函数内部的函数可以访问到第一层函数的局部变量
b = 20
def fn():
a = 10 # a定义在函数内部,所以它的作用域是函数内部,函数外部是访问不到的
print('函数内部:','a =',a) # 10
print('函数内部:','b =',b) # 20
fn()
print('函数外部:', 'a =', a) # NameError: name 'a' is not defined
print('函数外部:', 'b =', b) # 20
3 使用global()函数修改全局变量
语法格式
global 变量名
a = 20
def fn3():
# 如果希望在函数内部修改全局变量,则需要使用global关键字,来声明变量
global a # 声明在函数内部的使用a是全局变量,在去修改a,是修改的是全局的a
a = 10
print('函数内部:','a =',a)
fn3()
print(a)
运行结果
函数内部: a = 10
10 # 修改了全局变量 a
1.4 命名空间
1 命名空间实际上就是一个字典,是一个专门用来存储变量的字典
2 locals()用来获取当前作用域的命名空间
3 globals() 函数可以用来在任意位置获取全局命名空间
如果在全局作用域中调用locals()则获取的是全局命名空间,如果在函数作用域中调用,则获取的是函数的命名空间 返回是一个字典
locals()在函数外部调用locals()函数,获取全局变量
s = locals() # 当前的命名空空间
s['b'] = 100 # 像字典中添加key-value 就相当于在全局中创建了一个变量
print(b)
print(s)
运行结果
100
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000025B842BA1D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/python第11节/venv/44.py', '__cached__': None, 's': {...}, 'b': 100}
locals()在函数内部调用locals()函数,获取函数的变量
def fn4():
a = 10
s = locals() # 在函数内部调用locals()会获取到函数的命名空间
s['c'] = 20
# print(c),打印c会报错,这是一个与在函数外部的区别
print(s)
fn4()
运行结果
{'a': 10, 'c': 20} # s通过获取局部变量来生成字典
globals() 函数可以用来在任意位置获取全局命名空间
a = 80
def fn4():
b = 10
global_space = globals()
print(global_space)
fn4()
运行结果
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002F462A5A1D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/python第11节/venv/44.py', '__cached__': None, 'a': 80, 'fn4': <function fn4 at 0x000002F462B31E18>}
1.5 递归
1递归式的函数
递归简单理解就是自己调用自己
递归式函数,在函数中自己调用自己
2 递归式函数有两个条件
基线条件
问题可以被分解为最小的问题,当满足基线条件的时候,递归就不在执行了
递归条件
将问题可以分解的条件
练习1 定义一个函数求任意数的阶乘(n!)
def fn(a):
if a == 1: # 基线条件 判断n是否是1 如果是1不能再继续递归
return 1
return a * fn(a - 1) # 递归条件
b = fn(10)
print(b)
运行结果
3628800
1.6 递归的练习
练习1
创建一个函数 来为任意数字做幂运算 n ** i
def fn(n, i):
if i == 1:
return n
return n * fn(n, i - 1)
b = fn(4, 2)
print(b)
运行结果
16
练习2
创建一个函数,用来检测任意字符串是否是回文字符串,如果是返回True,如果不是返回False
什么是回文字符串?字符串从后往前读和从后往前读是一样的 例如 abcba
思路,使用切片
abcdefgfedcba
先去检测第一个字符和最后一个字符是否一致,如果不一致则不是回文字符串
如果一致,则看剩余部分是否是回文字符串
检查abcdefgfedcba 是不是回文
检查bcdefgfedcb 是不是回文
检查 cdefgfedc 是不是回文
…
检查 fgf 是不是回文
检查 g 是不是回文
def fn(a):
# 参数 s 就是用来检测是否是回文字符串 如果是返回True 如果不是返回False
# 基线条件
# 如果字符长度小于2,则肯定是回文
if len(a)<=1:
return True
# 第一个字符和最后一个字符不相等 则证明肯定不是回文
elif a[0] == a[-1]:
return True
return False
# 递归条件
return fn(a[1:-1]) # 判断除第一个和最后一个以外其他字符是否相同
print(fn('qp'))
print(fn('asdfdsa'))
运行结果
False
True