函数:
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
一.定义函数:
def(关键字)+函数名(遵循变量命名规则)+(): 函数体
函数名的本质(就是这个函数所在的内存地址)像这样的就是叫第一类对象.
1. 函数名是不可以变得,函数名赋值只是分享内存地址,这个函数本身的名字是不会变的,还是原来定义时的名字
def func(): passf = funcprint(func)print(f)两次运行结果:
2.函数名可以赋值:函数名指向的是这个函数的内存地址,当把这个函数名赋值给另一个变量名,两个变量都指向函数内存地址,所以用两个变量都可以调用这一个函数内存地址,即可以调用这个函数.
def func(): print(666)a = b =funca()b()func()
3.函数名可以作为容器类型(列表,元组,字典,集合)中的一项,可以做字典的键
def f1(): print('娃哈哈')def f2(): print('qqxing')l = [f1,f2]f1_func = l[1]f1_func()l[1]()
4.函数名可以作为另一个函数的参数
def login(): print('欢迎登陆')def index(auth): auth() #函数名的赋值,令auth = login,即autn() = login() print('欢迎来到首页')index(login)
5.函数可以作为另一个函数的返回值
def login_failed(): print('登录失败')def index(): print('欢迎来到首页')def login(uer,pwd): if uer == 'alex'and pwd == 'sb': return index #返回index()函数的print else: return login_failed #返回login_failed()的printres_func = login('alex','ssb') #调用返回 login_failded = res_funcres_func() #执行 login_failed()
二.函数的调用
函数调用本质是函数地址加(),那么函数名+()相当于调用
# 定义函数def printme( str ): "打印任何传入的字符串" print (str) return # 调用函数printme("我要调用用户自定义函数!")printme("再次调用同一函数")
三.参数和参数传递:
1.形参:在定义函数的时候使用
位置参数:根按照实参的位置把对应的值赋值给形参中的变量
关键字参数:也叫默认参数:在定义形参的时候,给变量进行赋值.后面使用的时候不用写入实参.若写实参,便重新赋值,使用实参的值.
混合参数:即括号里既有位置参数也有关键字参数,这时位置参数应该在前面,默认参数在后面
2.实参:在函数调用的时候给函数传递的值,实际执行的时候给函数传递的信息
位置参数:按照位置给形参进行传参
关键字参数:也叫默认参数:按照关键字给形参进行传参
混合参数:即括号里既有位置参数也有关键字参数,这时位置参数应该在前面,默认参数在后面
3.传参:给函数传递信息的时候将实际参数交给形式参数的过程被称为传参.
#函数定义def mylen(s1): """计算s1的长度""" length = 0 for i in s1: length = length+1 return length#函数调用str_len = mylen("hello world")print('str_len : %s'%str_len)
调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。
定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。
推荐写法:位置参数>动态位置参数>关键字参数>默认关键字参数
四.函数的返回值 (return):
当程序运行遇到return就结束函数,并选择性地向调用方返回一个表达式。
如果不写return默认返回None,有return没有内容返回的也是None
如果有返回值,应该定义"变量"接收返回值,return返回一个值就是本身的数据类型,返回多个值就就是元组形式返回.
五.函数进阶:
动态位置参数: *args #动态位置参数() 获取的结果是元组
动态关键字参数: **kwargs #动态关键字参数() 获取的结果是字典
动态位置参数输出: *args (先传参,然后看打印的顺序)
def eat(a,b,*args): print("我想吃",args,a,b)eat("土豆","西蓝花","大虾","卫龙","康帅傅") #我想吃 ('大虾', '卫龙', '康帅傅') 土豆 西蓝花
动态关键字参数输出: **args (先传参,然后看打印的顺序)
def f(e =33,f=88,**args): print("天涯",args,f,e) #天涯 {'args': 1, 'a': 1, 'b': 6, 'c': 8} 88 33f(args=1,a=1,b=6,c=8)
混合参数输出
def func(a,*arg,b=1,**kwargs): print(a,b,arg,kwargs)func(2,3,59,889,b=9,cc=98,dd=66) #2 9 (3, 59, 889) {'cc': 98, 'dd': 66}
解包和聚合
lst = [1,2,3,4,5,6]def func(*args): #聚合 (1,2,3,4,5,6) print(args) # 1 2 3 4 5 6func(*lst) #按顺序解包 func(1,2,3,4,5,6)dic = { "name":"alex","age":18}def func(**kwargs): #{"name":"alex","age":18} print(kwargs) func(**dic) #func(name='alex',age=18) 输出结果:
{"name":"alex","age":18}
三元运算符
语法: a if a >b else b
条件成立的结果 条件 条件不成立的结果
def func(a,b): g = a if a >b else b return gprint(func(9,8))
六.函数的嵌套
def f(): print(11) def f1(): print(22) def f2(): print(33) f2() f1() f()
七.函数的命名空间和作用域
从python解释器开始执行之后,就在内存中开辟了一个空间每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量 会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
python解释器在开始执行的时候会在内存中开辟一块空间,
每当遇到一个变量就会把变量名和值的对应关系记录下来,
当程序遇到函数时,解释器只会象征性的将函数名存储到内存
命名空间:存放名字与值的绑定关系的空间 内置命名空间 :python自带的内建命名空间,任何模块均可以访问,放着内置的函数和异常。 作用域 全局和局部,加载是在运行之后,代码之前 全局命名空间 :,代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间 作用域 全局和局部,加载是在运行代码的时候 局部命名空间 :在函数的运行中开辟的临时的空间叫做局部命名空间 作用域 在局部,加载是在调用的时候生命周期:
Local(局部命名空间)在函数被调用时才被创建,但函数返回结果或抛出异常时被删除。(每一个递归函数都拥有自己的命名空间)。
Global(全局命名空间)在模块被加载时创建,通常一直保留直到python解释器退出。
Built-in(内建命名空间)在python解释器启动时创建,一直保留直到解释器退出。
各命名空间创建顺序:python解释器启动 ->创建内建命名空间 -> 加载模块 -> 创建全局命名空间 ->函数被调用 ->创建局部命名空间
各命名空间销毁顺序:函数调用结束 -> 销毁函数对应的局部命名空间 -> python虚拟机(解释器)退出 ->销毁全局命名空间 ->销毁内建命名空间
python解释器加载阶段会创建出内建命名空间、模块的全局命名空间,局部命名空间是在运行阶段函数被调用时动态创建出来的,函数调用结束动态的销毁的。
加载顺序:内置>全局>局部
取值顺序:局部>全局>内置
作用域:
全局作用域:内置+全局
局部作用域:函数局部
.globs() 查看全局作用域中的变量和函数名
.locals() 查看局部作用于中的变量和函数名
#查看变量内容a = 5def func(): b = 3 print(b) print(locals()) #查看局部变量与内容func()print(globals()) #查看全局变量与内容
八.global和nonlocal关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字.
global:不可变类型在局部修改时使用global,可变数据类型在局部修改时可以使用.add或者.applend等,在局部改全局变量
nonlocal:改变最近的父级变量(上一级), 如果上级没有能够改变的就继续向上走,直到最外层函数停止.
num = 1def fun1(): global num # 需要使用 global 关键字声明 print(num) num = 123 print(num)fun1()print(num) 输出结果: 1 123 123
def outer(): num = 10 def inner(): nonlocal num # nonlocal关键字声明 num = 100 print(num) inner() print(num)outer()
九.默认参数的陷阱
def func(l=1): l += 1 print(l)func()func()func()输出结果:222
lst = []def func(a,l = lst): l.append(a) print(l)func(1) # [1]func(2,[]) # [2] func(3) # [1,3]
def defult(a,l = []): l.append(a)print(l)defult('welkin')defult('alen')#["welkin"]#["welkin","alen"]
十.闭包
内部函数使用了外部函数的变量,内部函数就是一个闭包.
应用:缓存(把一个值存储在内存里,可以快速将数据下载下来)和装饰器(函数写完之后添加功能)
def func(*args):# sum_num = 0# for num in args:# sum_num += num# def inner():# return sum_num# return inner## inner = func(1,2,3,4)# inner()