举例说明函数的特殊用法:
- 变量可以指向函数
def test(): pass f = test f()
- 函数名是一个变量
test = 10 test()
- 函数可以作为参数使用
def fun(f): f() fun(test)
变量的作用域:
- 概念:变量的作用域指的是一个变量可以被使用【访问】的范围。程序中的变量并不是在任何地方都可以访问的,访问的权限取决于这个变量被定义在什么位置【直接定义,语句中,函数中】
- 作用范围的划分:局部作用域【L:local】、函数作用域(体现在闭包中)【E:enclosing】、全局作用域【G:global】、内键作用域(内置作用域)【B:Built-in】
- 变量的查找规则:L——>E——>G——>B(注意:全局作用域和内键作用域并没有严格顺序,主要由先后顺序决定查找规则)
变量的查找规则:
- 四种变量由不同的命名
num3 = 30 #全局作用域 num4 = int(2.9) #内置作用域【系统内置功能返回的值赋值给一个变量】 def outer(): num1 = 10 #函数的作用域 def inner(): num2 = 20 #局部作用域【局部作用域并不是绝对的】 print(num1,num2,num3,num4) #10 20 30 2 #结论:在闭包的内部函数中,可以访问全局,内置,函数 return inner f = outer() f()
- 四种变量有相同的命名【就近原则】
x = int(3.2) x = 10 def outFunc(): x = 20 def innerFunc(): x = 30 print(x) #30 #结论:如果所有的变量同名,就近原则,看哪个语句距离此语句最近 return innerFunc f1 = outFunc() f1()
注意:python中只有模块【module】,类【class】和函数【def,lambda】会引入新的作用域,在模块外面是访问不到的。其他代码块,如:while语句,for语句,try-except语句是不会引入新的作用域的,即在这些语句中定义的变量,在语句外面也可以进行访问
全局变量和局部变量【尽量避免两种变量重名情况,如发生则就近原则】:
- 全局变量:定义在函数外面,在当前整个py文件中都可以任意访问
- 局部变量:定义在函数中,只能在当前函数中访问
global和nonlocal关键字的使用:
- 如果在函数内部出现了和全局变量重名的局部变量,而在局部变量定义之前要访问全局变量,则需要使用global关键字对全局变量进行声明
num = 1 def fun1(): #需求:访问全局num #解决办法:在访问全局变量之前作出声明 global num print(num) #1 num = 123 print(num) #123 fun1()
- nonlocal的使用只能出现在闭包中【将小作用域范围变大一层】
x = 0 #全局作用域 def outer(): x = 1 #函数作用域 def inner(): nonlocal x #将此部分x的作用域变大,即将变量的局部作用域修改为函数作用域 x = 2 #局部作用域 print("inner:",x) #2 inner() print("outer:",x) #2 outer() print("global",x) #0
迭代器:
- 可迭代对象
- 概念:可以直接作用于for循环的对象【实体】被称为可迭代对象:Iterable
- 分类:可以直接作用于for循环的数据类型:集合数据类型,包含list,tuple,dict,set,string generator,包含()生成器和yield的生成器
- 判断:isinstance()【instance:对象,实体,实例】可以用来判断一个对象(实体)是否可迭代对象 isinstance(数据,Interable)
#第一步:导入模块 from collections import Iterable #import collections #第二步:判断 print(isinstance([],Iterable)) #True print(isinstance((),Iterable)) #True print(isinstance({},Iterable)) #True print(isinstance(set([]),Iterable)) #True print(isinstance("hello",Iterable)) #True print(isinstance((i for i in range(10)),Iterable)) #True print(isinstance(10,Iterable)) #False print(isinstance(True,Iterable)) #False
- 迭代器
- 概念:不但可以直接用于for循环,还可以使用next()函数进行获取元素值,同时符合这两种条件的数 据被称为迭代器【Interator】,只有生成器是迭代器
- 判断:isinstance()可以用来判断一个对象【实体】是否是迭代器
#第一步:导入模块 from collections import Iterator #import collections print(isinstance([],Iterator)) #False print(isinstance((),Iterator)) #False print(isinstance({},Iterator)) #False print(isinstance(set([]),Iterator)) #False print(isinstance("hello",Iterator)) #False print(isinstance((i for i in range(10)),Iterator)) #True print(isinstance(10,Iterator)) #False print(isinstance(True,Iterator)) #False #可以使用系统内置的功能iter(),可以将可迭代对象转换为迭代器【除了生成器之外的可迭代对象】 list1 = [41,51,5] a = iter(list1) print(next(a)) list2 = [41,546,12] b = iter(list2) while True: try: x = next(b) except StopIteration: print("元素已经获取完成") break
注意:可迭代对象不一定是迭代器,迭代器肯定是可迭代对象
装饰器:简单装饰器、带参数装饰器、使用@标识符将装饰器直接应用到函数、带有不定长参数的装饰器、将多个装饰器应用在同一个函数上
- 本质:dectorator 增强一个函数的功能,又不修改原有函数,在代码运行期间动态给函数增加功能方式装饰器实际上是一个闭包【将需要装饰的函数作为参数传递给闭包,然后将装饰之后的结果返回】
- 优势:在不用修改源代码的前提下增加函数功能【动态性】
#简单装饰器 #第一步:书写闭包 #第二步:给外部函数设置参数 def outer(fun): def inner(): #第三步:在内层函数中调用需要被装饰的函数 fun() #第四步:增加新功能 print("Let's go outside") return inner #第五步:使用闭包 f = outer(now) #函数可以作为参数使用 f()
注意:增加的功能可以写在原函数调用的前面或者后面,没有严格的区分。上述代码中outer被称为装饰器,inner被称为装饰器的工作核心
#有参数的装饰器 def getAge(age): print(age) #问题:输出若为负数,则不符合常理 getAge(10) getAge(-5) #需求:用装饰器实现:当用户输入的age为负数的时候,将其置为0 def outer2(f): def inner2(age): f(age) if age > 0: print(age) else: print("输出有误") return inner2 f2 = outer2(getAge) f2(-5)
注意:当原函数有参数,装饰器的额作用是为了操作原函数中的参数,则要在闭包inner内传入参数,调用的时候也给入参数
#使用@标识符将装饰器直接应用到函数 def wrapper(f): def inner(num): if num < 0: num = 0 f(num) return inner @wrapper def getAge1(age): print(age) getAge1(-5)
注意:使用@之后,装饰器必须先被定义,然后再使用到原函数,此时原函数也相当于被增加新功能
#4.带有不定长参数的装饰器 def wrapper(fun): def inner(*args,**kargs): fun(*args,**kargs) print("hello") #新功能 return inner @wrapper def fun1(a,b): print(a + b) #30 hello fun1(10,20) @wrapper def fun2(a,b,c): print(a * b * c) #6 hello fun2(1,2,3)
注意:将一个装饰器应用到不同函数上
#5.将多个装饰器应用在同一个函数上 def wrapper1(fun): def inner(*args,**kargs): fun(*args,**kargs) print("hello world1") return inner def wrapper2(fun): def inner(*args,**kargs): fun(*args,**kargs) print("hello world2") return inner @wrapper1 @wrapper2 def test(): print("test") test() #test hello world2 hello world1
注意:多个装饰器应用于同一个函数的时候,原函数只被执行一次,并且是就近原则执行【谁最后出现,谁最先被执行】
递归的概念及使用:斐波那契数列与求和问题
概念:一个函数调用本身,被称为函数递归【递归调用】。递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复无须用条件控制【但凡使用循环可以解决的问题,一般使用递归解决】
使用递归解决问题需要考虑的因素:
- 找到一个临界值【临街条件】
- 寻找相邻两次循环之间的关系【公式】
#斐波那契数列 ''' 1 2 3 4 5 6 7 8 9 10 报数 1,1,2,3,5,8,13,21,34,55,89,,,,,斐波那契数列 ''' #规律:a.临界值:第一个位置和第二个位置上的数是固定的,都是1 # b.公式:第n个位置上的数 = 第n-1个位置上的数 + 第n-2位置上的值 def func(num): if num == 1 or num == 2: return 1 else: return func(num-1) + func(num-2) print(func(10)) #55
#计算1到某个数之间的所有整数的和 def func1(num): if num ==1: return 1 else: return func1(num-1) + num print(func1(10))