函数
- 1、它是什么?
- 2、为什么要用它?
- 3、怎么用?
函数
什么是函数?
函数就是工具
为什么用函数?
增强代码的可读性,解决代码重复
怎么用函数?
函数分类:
1,内置函数:Python提供的函数
2,自定义函数:我们自己可以根据自己的需求封装一个函数
定义函数
1,先定义 后调用
a.申请内存空间保存函数体代码
b.将上述内存地址绑定函数名
c.定义函数不会执行函数体代码,但会检测语法
#语法 def 函数名(参数1,参数2,参数3,...): '''注释''' 函数体 return 返回的值 2,调用
a.通过函数名找到函数内存地址
b.加括号就触发函数体代码执行
#定义阶段 def foo(): print('from foo') bar() def bar(): print('from bar') #调用阶段 foo()
定义函数的三种形式
#1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印
def func()
#2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
def func(x,y)
#3、空函数:设计代码结构
def func():
pass
#有参数 #定义阶段 def tell_tag(tag,n): print(tag*n) #无参数 def tell_msg(): print('hello world') #调用阶段 tell_tag('*',12) tell_msg() tell_tag('*',12)
函数返回值
无return->None return 1个值->返回1个值 return 逗号分隔多个值->元组
应用
#1、位置参数:按照从左到右的顺序定义的参数 位置形参:必须传参数,多一个不行,少一个也不行 位置实参:按照位置给形参传值,传入的值必须与形参位置一一对应 def func(x, y): print(x, y) func(1, 2) #2、关键字参数:按照key=value的形式定义的实参 无需按照位置为形参传值 注意的问题: 1. 关键字实参必须在位置实参右边 2. 对同一个形参不能重复传值 3. 可以不用按照顺序传参 def func(**kwargs): print(kwargs) func(y=2, a=1) #3,混合使用: 1. 关键字实参必须在位置实参右边 2. 对同一个形参不能重复传值 def func(x, y, **kwargs): print(x, y) print(kwargs) func(1, y=2, a=1) #,4、默认参数:形参在定义时就已经赋值 可以传值也可以不传值 注意的问题: 1. 只在定义时赋值一次 2. 默认参数的定义应该在位置形参右面 3. 默认参数通常应该定义成不可变类型 def func(x,y=2): print(x,y) func(1) #5、可变长参数: 可变长指的是实参值的个数不固定 而实参有按位置和按关键字两种形式定义, 针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs def foo(a,b,c): print(a,b,c) def info(*args,**kwargs): foo(*args,**kwargs) info(1,b=3,c=4) #6、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
def foo(x, y, *args, a=1, b, **kwargs): print(x, y) print(args) print(a) print(b) print(kwargs) foo(1, 2, 3,b=3, c=4, d=5)
名称空间与作用域
什么是名称空间? 存放变量名的地方 名称空间的分类 1.内置名称:Python内置的名字 存活周期:Python启动则产生,Python关闭则销毁 2. 全局名称:运行顶级代码所产生的名称,不是函数定义的,也不是内置的。
存活周期:Python执行前则产生,Python执行完则销毁
3.局部名称:在调用函数时,运行函数体代码过程产生的函数名
存活周期:在调用时存活,调用结束则销毁
名称空间加载顺序
内置名称空间 > 全局名称空间 > 局部名称空间
销毁顺序
局部名称空间 > 全局名称空间 > 内置名称空间
名称访问顺序(先在自己找没有,去外面找没有,在去外面外面找)
局部名称空间 > 全局名称空间 > 内置名称空间
x = 123 def f1(): # x = 111 def f2(): # x = 999 print(x) f2() f1()
作用域
#1、作用域即范围 - 全局范围:全局存活,全局有效 - 局部范围:临时存活,局部有效 #2、作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,
x=1 def f1(): def f2(): print(x) return f2 # x=100 def f3(func): x=2 func() # x=10000 f3(f1())
#3、查看作用域:globals(),locals()
def foo(): global x # 局部修改全局 x = 100 foo() print(x)
def foo(): x = 100 def fune(): nonlocal x # 局部变量修改局部变量 x = 123 fune() print(x) foo()
函数对象
1.函数可以被引用
def add(x, y): print(x + y) func = add func(1, 2)
2.函数可以当做另外一个函数的参数
def add(x, y): print(x + y) # add(1,2) def info(x, y, add): return add(x, y) # info(1, 2, add)
3.函数可以当做另外一个函数的返回值
def add(x, y): print(x + y) def bar(): return add func = bar() func(1, 2)
4.函数可以当做容器的一个元素
def add(x, y): print(x + y) dic = {"add":add} dic["add"](1,2)
闭包函数
什么是闭包函数?
“闭”:闭是关闭,“包”:包是包裹起来,闭包函数把一个函数定义
在另一个函数里,该函数对外层名字作用域的引用。
可以通过函数__closure__属性,查看闭包函数所包裹外部的变量
闭包用途
#第一种:直接把函数体需要的参数定义为形参 def f1(x,y): print(x,y) f1(1,2) # 第二种:闭包 def outer(x): def inner(y): nonlocal x x += y return x return inner a = outer(5) print(a(1)) #6
装饰器
为什么是装饰器? 装饰器是可以在被装饰对象上添加新功能,并且不修改代码 为何要有装饰器? 装饰器是开发封闭原则,对修改封闭,对扩展开发。 import time def index(x): print("index:%s"%x) def outer(func): def waper(*args,**kwargs): start = time.time() func(*args,**kwargs) stop = time.time() print(stop-start) return waper insex = outer(index) index(1)
语法糖:在被装饰的对象正上方单独一行写@装饰的名字
#1. 加载顺序:自下而上 # 2. 执行顺序:自上而下 def outer(func): def waper(*args,**kwargs): start = time.time() func(*args,**kwargs) stop = time.time() print(stop-start) return waper @outer def index(x): time.sleep(0.3) print("index:%s"%x) index(1)
装饰器模板
# 无参装饰器 import time def outer(func): def waper(*args,**kwargs): start = time.time() res = func(*args,**kwargs) stop = time.time() print(stop-start) return res return waper @outer def index(): print("222") index() # 有参装饰器 def demo(x): def outer(func): def waper(*args,**kwargs): res = func(*args,**kwargs) return res return waper return outer @demo(x=1) def index(): print("111") index()
迭代器
什么是迭代? 迭代是一个重复的过程 什么是迭代器? 迭代器就是迭代的工具。 为什么用迭代器? 可提升代码的可读性,减少重复代码 什么是可迭代对象? 可迭代对象就是指内置方法里有__iter__方法 什么是迭代对象? 迭代对象就是指内置方法里有__iter__方法又有__next__方法 迭代器 优点: 1.统一取值 2.节省内存空间 缺点: 1.没有索引 2.只能next取,如果值取完了还继续取值会抛出异常,而我们要自己捕获异常
迭代器对象的使用
dic = {"a":1,"b":2}
a = dic.__iter__()
print(a)
print(a.__next__())
print(a.__next__())
for循环
dic = {"a": 1, "b": 2}
for k in dic:
print(dic[k])
# for 循环
# 执行 in 后对象dic.__iter__(),得到一个迭代对象iter_dic
# 执行next(iter_dic),赋值给k然后继续循环代码
# 重复执行next(iter_dic),直到把值取完,
# 捕捉到异常StopIteration,循环结束
生成器
什么是生成器? 函数内部yield关键字,那么函数名就得到结果就是生成器 def func(): print(">>>:1") yield 1 print(">>>:2") yield 2 print(">>>:3") yield 3 print(func()) 生成器就是迭代器 因为生成器有__iter__方法和__next__方法 def func(): print(">>>:1") yield 1 print(">>>:2") yield 2 print(">>>:3") yield 3 print(func().__iter__()) print(func().__next__())
三元表达式、列表推导式、生成器表达式
三元表达式(if 语句的简写形式) 语句: 成立 if 条件 else 不成立 x = 1 y = 2 res = x if x > y else y print(res)
列表推导式 # 通常写法 egg_list = [] for i in range(5): egg_list.append('鸡蛋%s' % i) print(egg_list) # 列表推导写法 res = ['鸡蛋%s' % i for i in range(5)] print(res)
# 表达式 # l = [表达式 for x in 可迭代对象 if 条件 else 不成立 ] res = ['鸡蛋%s' % i for i in range(5)] print(res) # 生成器表达式 # i = (表达式 for x in 可迭代对象 if 条件 else 不成立 ) egg = ('鸡蛋%s' % i for i in range(5)) print(egg.__iter__()) print(egg.__next__()) print(egg.__next__()) print(egg.__next__())
递归
什么是递归? 递归本质就是循环(递归循环可以节省内存) 递归是函数调用的一种,可以直接或者间接的调用本身 ps:默认递归为1000层 #直接调用本身 def f1(): print('from f1') f1() f1() # #间接调用本身 def f1(): print('from f1') f2() def f2(): print('from f2') f1() f1() 递归不应该无限的循环而是在满足某种条件是结束调用 return
递推,回溯
回溯:一层一层的调用 递推:满足某种结束条件时,结束递归调用然后一层一层的返回 def f1(x): if x == 0: return 10 return f1(x-1) + 1 print(f1(5)) #15
匿名函数
什么是匿名函数? 匿名就是没有名字的函数 res = (lambda x,y:x+y)(1,2) print(res) #有名函数与匿名函数的对比 有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能 匿名函数:一次性使用,随时随时定义
内置函数


浙公网安备 33010602011771号