函数基础知识
1. 函数的作用(面向函数编程的优点):
a. 解决代码冗余
b. 提高代码可读性
c. 提高了代码的重用性
d. 增强了代码的可扩展性
e. 解耦:把一个大功能尽量拆开来,尽量细化成多个小功能,并且功能与功能之间的影响减到最小
面向对象编程:功能与功能之间耦合很紧密
2. 函数基本形式
def func(arguments): # def 定义函数 ''' 注释部分 :param arguments: :return: ''' '''函数体部分''' return arguments # return 函数结束并返回arguments func('test') # 调用函数 并传入字符串test作为参数
3. 关键字 return
1. 作用
a. 返回值
b. 结束函数的执行
2. 返回值
a. 单个值(任意类型的对象)
b. 多个值(示例 return 1,2,3) 需用','分隔,接收时数据类型为元组,可以用一个变量或多个变量接收,多个变量接收需注意个数保持一致
c. 当函数没有return时,默认返回值为None
4. 函数的参数
1. 实参和形参
def mylength(name): # name参数 站在函数定义的角度上,所有的函数都是形式参数(形参) print(name) n = 0 for i in name: n += 1 print(n) mylength("alex") # alex参数 站在函数调用的角度上,所有的参数都是是实际参数(实参)
2. 位置参数、关键字参数、默认参数(任意数据类型)
def func(parameter1, parameter2, default_parameter=None): ''' :param parameter1: 位置参数1 必须传的参数 :param parameter2: 位置参数2 :param default_parameter: 默认参数 可以不传值 默认None :return: ''' print(parameter1, parameter2, default_parameter) func(1,2) # 按位置传参,即顺序传参 func(parameter2=1,parameter1=2) # 按关键字传参,即根据不同参数名传参,无所谓顺序 func(1, parameter2=2) # 混用:必须先按位置传参,再按照关键字传参
3. 当函数中的默认参数为可变数据类型时
def demo(a = []): a.append(123) print(a) demo() # 此次没有传值 所有a=[] 执行完后a=[123] demo([]) # 传入[] a=[] 执行完后a=[123] demo() # 没有传值 此时a=[123] 执行完后a=[123, 123]
注意:因为参数a是可变数据类型(列表、字典),在第三次调用函数时,内存中保存的a并不是空列表,而是第二次执行完毕的结果, 所以,第三次执行完是有两个元素的
4. 动态参数
* 是动态参数的表识
a. *args 代表位置参数
b. **kwargs 代表关键字参数
def func1(*args): # 站在函数定义的角度上,*做聚合用,将参数合成元组 print(*args) # * 在这里起打散作用 print(args) # 聚合之后是元组 func1(1, 2, 3) def func2(*args): print(*args) print(args) li = (1, 2, 3) print(*li) # 打散作用 func1(*li) # 站在函数调用的角度上,*做打散用,将一个列表或元组打散成多个参数 def func3(**kwargs): # 站在函数定义的角度上,**做聚合用,将参数合成字典 print(kwargs) func3(a=1, b=2) def func4(**kwargs): print(kwargs) d = {'c': 3, 'a': 1, 'b': 2} func4(**d) # 站在函数调用的角度上,**做打散用,将一个字典打散成多个参数
5. 命名空间和作用域
命名空间又叫做名称空间,分为三种
启动python
a. 先加载Python内置命名空间 这里边存放了python解释器为我们提供的名字:input,print,str,list,tuple等
b. 加载全局命名空间的名字,从上到下加载,除去函数内部,其余都是全局空间
c. 加载局部空间中的名字,调用该函数的时候,从上到下加载
局部命名空间之间的数据不能共享,局部命名空间可以调用全局变量, 对于局部命名空间来说,自己有就用自己的,自己没有就用全局的
作用域,即不同命名空间下的变量的作用域
内置的命名空间,在任意地方都可以用
全局的命名空间,在我们写的代码里任何地方
局部命名空间,在自己写的函数内使用
范围从大到小:内置 全局 局部--->局部
作用域: 站在范围小的局部,如果有 用局部,局部没有往上找,就近原则往上找,找到第一个可用的名字就用它
PS:对于不可变的数据类型,如果想在函数内部修改想对全局生效,就要进行global生明;对于可变数据类型,如果想修改直接修改即可
6. 关键字 global nonlocal
globals()全局,不受影响
global 变量 #在局部里面改变全局变量,只改变全局变量,不影响其他的变量
locals()局部,放局部里就只显示局部的
nonlocal 变量 #只改变局部里的变量,从内部往外部找到的第一个变量名
a = 0 def demo1(): a =1 def demo2(): global a # global,只是改变全局变量,不会影响其他局部的变量 a=2 print(a) demo2() print(a) demo1() print(a)
a = 0 def demo1(): a = 1 def demo2(): nonlocal a # 只改变上一层的a---->a=2 a = 2 print(a) demo2() print(a) demo1() print(a)
7. 函数的本质
函数名(是一个存着函数地址的变量名)是第一类对象的概念
函数名首先是一个函数的内存地址,可以赋值,可以作为其他列表等容器的元素,可以作为函数的参数返回
8. 小练习(斐波那契数列)
# 当长度小于多少时 l = [1,1] while len(l)<20: l.append(l[-2]+l[-1]) print(l) #当小于某一个数时 l = [1,1] while l[-1]<40000: l.append(l[-2]+l[-1]) print(l)