what's the 函数?
函数就是将要调用的内容打包装进def()里面,在不调用的情况下只读入内存不执行任何操作,若要调用时再一步一步进行。
函数的作用:
一、使组织结构变得清晰
二、重复的代码可以用调用函数的方式解决,解决代码冗余问题
三、使维护变得更加便捷
函数的定义:(函数也是变量,所以要先定义后使用)
def wrapper(参数1,参数2,*args,默认参数,**kwargs):
'''注释:函数功能和参数说明'''
函数体
return 返回值#return是返回值,可以没有,不过没有的话就返回了None
函数的参数:有形参和实参两种,形参指的是定义时写在def后面的括号里,实参指调用时才会用到的代码的实际的参数,形参的作用就是在定义阶段帮实参占位置用的。
形参:位置形参、默认参数、动态参数、命名关键字参数
位置形参:按照从左到右的顺序定义,必须被传值,多一个不行,少一个不行。(值经常变化时可以将其定义为位置形参)
默认参数:在定义函数时就已经为形参赋值,调用阶段可以不用传值(值基本不变时可以用默认参数,调用阶段就可以忽略不传值。比如矿工的性别、一个农村小学的学生的籍贯等等)。需要注意的因素:一:默认参数必须放在位置形参后面;二:默认参数通常要定义成不可变类型;三:默认参数只在定义阶段被赋值一次。
动态参数:实参的长度不固定是就用动态参数*args*和*kwargs,可以接受任意类型
命名关键字参数:定义在*后的形参,这类形参,必须被传值,而且要求实参必须是以关键字的形式来传值,如:
def people(*args,name='jack',age):
print(args)
print(name)
print(age)people1(name='jack',age=18)
people2(1,2,2,3,age=10)#1,2,2,3被*args接收,以元祖形式返回
形参的定义顺序为:位置形参,默认参数,*args,命名关键字参数,**kwargs
实参:位置实参、关键字参数(位置实参必须在关键字实参前面)
位置实参:与位置形参相对应,统称为位置参数
关键字参数:以key=value的形式指名道姓的传值,可以不用像位置实参一样与形参一一对应
def func(name,age=18,*args,z,**kwargs):
'''
name是位置参数,age是默认参数(传参时可以传也可以不传),
*args是接收除了以关键字传参为传参方式的其他传参方式的动态参数,以元祖形式返回
z是命名关键字参数,传参时只能用关键字方式且必须被传值
**kwargs是接收以关键字传参为传参方式的动态参数
'''
print(name)
print(age)
print(args)
print(z)
print(kwargs)
func(1,2,3,4,5,z=10,a=1,b=2)
#1
#2
#(3, 4, 5)
#10
#{'a': 1, 'b': 2}
函数的调用:函数名加括号即调用
命名空间:内置命名空间、全局命名空间、局部命名空间
加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
相对应的变量即全局变量和局部变量,局部变量的取值顺序为:
在局部调用:局部命名空间->全局命名空间->内置命名空间;
在全局调用:全局命名空间->内置命名空间
函数的嵌套:定义的函数中可再定义函数,内部的函数就是嵌套进去的函数,要记住凡是函数都有返回值return,没有的默认return None
#函数嵌套简易模型
def f1():
def f2():
def f3():
print('from f3')
print('from f2')
f3()
print('from f1')
f2()
# print(f1)#这里只打印f1的内存地址,因为没有调用
f1()#调用f1函数
'''
from f1
from f2
from f3
'''
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。函数的作用域关系在函数定义阶段就已经固定,与调用位置无关,无论函数在何处调用,都需要回到定义阶段去找对应的作用域关系
闭包函数:在函数内部再定义一个函数,该内部函数包含对外部作用域,而不是对全局作用域名字的引用那么该内部函数就叫闭包函数。(该函数即使不return也算闭包函数)
闭包函数的特点就是自带作用域,即始终携带其外部作用域的变量,即使在调用时在其外部再设置一个不同值的相同变量也不能改变其携带的变量的值。
定义闭包函数的基本形式:
def 外部函数名():
内部函数需要的变量
def 内部函数():
引用外部变量
return 内部函数
举个小栗子:
def func():#以下缩进内容就是一个闭包函数
name='alex'
def bar():
print(name)
return bar
b=func()#因为func()return出了bar,所以b就等于bar
b()#这个b()就是bar(),就是一个闭包函数
查看闭包函数的一个方法:print(b.__closure__[0].cell_contents)
b就是指闭包,__closure__指查看携带的变量的id,[0]指的是携带的第一个变量,cell_contents值的是查看携带的变量的值。
闭包函数的一个应用就是装饰器,装饰器的诞生是因为代码的修改必须遵循开放封闭原则——已经实现功能的代码不能被修改,但是可以被扩展。就是因为不能被修改,所以才有了装饰器,以起到不修改源代码的前提下对其效果进行修改的作用。
装饰器的基本形式:
#装饰器
def wrapper(func):
def inner(*args,**kwargs):#定义函数的时候——*参数的聚合
ret = func(*args,**kwargs) #调用函数的时候——*参数的打散
#func是被装饰的函数,ret是被装饰函数的返回值
return ret #把被装饰的函数的返回值返回给调用者
return inner
装饰器本质可以使任意可调用对象,被装饰的对象也可以是任意可调用对象。
调用装饰器的方法是在要调用的函数的正上方@装饰器,该方式名为语法糖。
import time#导入时间模块,关于模块的知识之后会讲
def timer(func):#定义一个装饰器
def inner(*args,**kwargs):
start=time.time()#开始时间
time.sleep(2)时间停滞两秒
ret=func(*args,**kwargs)
print(time.time()-start)#结束时间-开始时间,得到的是运行时