文章目录
1. 函数简介
- 函数也是一个对象
- 函数的语法
def 函数名(形参1,形参2,形参3…):
代码块
注:函数名必须符合标识符的规范(可以包含字母、数字、下划线但是不能以数字开头)
print是函数对象(指向该函数的地址),print()是调用函数
2. 函数的参数
2.1 形参和实参
- 形参(形式参数) 定义形参就相当于在函数内部声明了变量,但是并不是赋值
- 实参(实际参数)指定了形参,那么在调用函数时必须传递实参,实参将会赋值给对应的形参,简单来说有几个形参就要有几个实参
2.2 函数的传递方式
- 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参
- 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递
- 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面去
- 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如果用户没有传递,则默认值就会生效
- 实参类型可以是int、str、布尔值、元组等所有的类型
-
- 关于对函数中的变量进行修改是否影响其他变量的问题,主要看他们是否指向同一对象,回顾08的可变对象章节
在函数中对形参进行赋值,不会影响其他的变量
def fn4(a):
a = 20, #给a重新赋值,开辟一个新的对象地址,
print('a =',a,id(a))
c = [1,2,3]
fn4(c[:])
print('c =',c,id(c))
a = [20, 2, 3] 20703032
c = [1, 2, 3] 20116664
-------------------------
def fn4(a):
a[0] = 20, #a是一个列表,修改的对象与c指向统一对象
print('a =',a,id(a))
c = [1,2,3]
fn4(c)
print('c =',c,id(c))
a = [20, 2, 3] 5043384
c = [20, 2, 3] 5043384
修改列表a而不影响列表c的方法:
给列表c创建一个副本,使用方法c.copy或者给c进行切片c[:]
def fn4(a):
a[0] = 20, #a是一个列表,修改的对象与c指向统一对象
print('a =',a,id(a))
c = [1,2,3]
fn4(c.copy) / fn4(c[:])
print('c =',c,id(c))
2.3 不定长参数
- 定义函数时,可以在形参前面加一个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到一个元组中
- 带*号的形参只能有一个,可以和其他参数配合使用
- *形参只能接受位置参数,不能接受关键字参数
注:不定长参数不一定都要写在后面,但注意带*的参数后面的所有参数,必须以关键字形式来传递
- **形参可以接收其他的关键字参数,它会将这些参数统一保存到字典当中。字典的key就是参数的名字,字典的value就是参数的值, **形参只有一个,并且必须写在所有参数的后面
3. 参数的解包
• 传递实参时,也可以在序列类型的参数前添加星号* (若序列类型为字典,则使用 **),这样它会自动的将序列中元素依次作为参数传递
• 要求序列中的元素的个数必须和形参的个数一致
def fn(a,b,c):
print('a =', a)
print('b =', b)
print('c =', c)
t = (20,30,40)
fn(*t)
4. 函数的返回值
- 返回值就是函数执行以后返回的结果,或通过return来指定函数的返回值
- return后面可以跟任意对象,返回值可以是一个函数
- 在函数中return一旦执行函数自动结束,跳出该层函数
5. 文档字符串
- help( )是Python中内置函数,通过help( )函数可以查询Python中函数的用法
在定义函数时,可以在函数内部编写文档字符串,问档字符串就是对函数的说明
def fn(a:bool,b:int,c:str)->int:
'''
这个函数式一个文档字符串的实例
参数
a:作用 类型 默认值......
b:作用 类型 默认值......
c:作用 类型 默认值......
'''
return 100
help(fn)
6. 函数的作用域(scope)
作用域指的是变量有效的区域,在Python中共有两种作用域
全局作用域和函数作用域
- 全局作用域在程序执行时创建,在程序执行结束时销毁
所有函数以外的区域都是全局作用域
在全局作用域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进行访问 - 函数作用域
函数作用域在函数调用时创建,在调⽤结束时销毁
函数每调用一次就会产生一个新的函数作用域
在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问 - 函数内部可以访问外部函数的变量 / 全局变量,但反之不行
- 函数内部的变量为访问最近自己的变量
a = 20
def fn2():
a = 30
def fn3():
a = 40
print('fn3中','a = ',a)
fn3()
print('fn2中','a=',a)
fn2()
print('函数外面的a = ',a)
输出:
fn3中 a = 40
fn2中 a= 30
函数外面的a = 20
- 如果通过函数内部修改全局变量,则使用global关键字,来声明变量,声明在函数内部使用的变量a是全局变量,则此时在去修改a时,就是在修改全局变量
a = 30
def fn1():
a = 20
def fn2():
global a
a = 10
print('fn2中的a = ',a)
fn2()
print('fn1中的a = ',a)
fn1()
print('函数外部的a = ',a)
输出
fn2中的a = 10
fn1中的a = 20
函数外部的a = 10
7. 命名空间(该函数作用不太大)
-
命名空间实际上就是一个字典,是一个专门用来存储变量的字典
-
locals ( )用来获取当前作用域的命名空间
如果在全局作用域中调用locals( )则获取全局命名空间,如果在函数作用域中调用locals( )则获取函数命名空间 -
返回值均是一个字典
获取全局命名空间
a = 20
def fn3():
pass
s = locals()
print(s)
输出:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x012C8310>, '__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'C:/Users/bin/Desktop/logic教育课件资料/基础资料-第十讲/课堂源码/命名空间.py',
'__cached__': None, 'a': 20,
'fn3': <function fn3 at 0x0128A6A8>, 's': {...}}
------------------------------
在上述代码中增加下列代码块,会出现报错
print(c) # NameError: name 'c' is not defined
现不使用直接给c赋值的语句(c=赋值),
而使用命名空间的方式去添加变量c,
s['c'] = 100
print(s)
输出:
不会报错,且会在上述输出的结果中增加{'c':100}这个键值对
此操作纯粹秀操作,正常都是使用直接给c赋值的方式
同理,把locals()放置函数内部,则获取函数命名空间
def fn4():
a = 10
s = locals() # 获取函数内部的命名空间
s['b'] = 20 #通过使用命名空间添加变量
print(s)
fn4()
输出
{'a': 10, 'b': 20}
-----------------------
通过函数命名空间的方法去修改全局变量
使用globals()
a = 20
def fn4():
s = globals()
s['a'] = 30
print(s)
fn4()
print(a)
输出:
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x01618310>,
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'C:/Users/bin/Desktop/logic教育课件资料/基础资料-第十讲/课堂源码/命名空间.py',
'__cached__': None,
'a': 30, 'fn4': <function fn4 at 0x015DA6A8>}
30
8.递归函数
- 递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,在去解决问题。
- 递归式函数有2个条件:
- 基线条件:问题可以被分解为最小问题,当满足基线条件时,递归就不执行了
- 递归条件:可以将问题继续分解的条件
用递归的方式求任意数的阶乘
1.基线条件
def fn(x):
if x==1:
return 1
else:
return x*fn(x-1)
fn(任意数)
--------------------------
利用递归函数,
定义一个函数用来检测一个任意字符是否是回文字符如果是返回True,
如果不是返回False
def fn(s):
if len(s)<2:
return True
elif s[0] != s[-1]:
return False
else:
return fn(s[1:-1])
s = 'abcdfefdcba'
print(fn(s))