坚持! 虽然每天刷的面试题不多, 但是一直坚持下去, 总会发现自己存在的价值! 今日份开始!!!部分代码, 图片等资源来源于网上
1.闭包?
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
很晦涩很难理解啊!!我们来看一段代码
1 #闭包函数的实例 2 # outer是外部函数 a和b都是外函数的临时变量 3 def outer( a ): 4 b = 10 5 # inner是内函数 6 def inner(): 7 #在内函数中 用到了外函数的临时变量 8 print(a+b) 9 # 外函数的返回值是内函数的引用 10 return inner 11 12 if __name__ == '__main__': 13 # 在这里我们调用外函数传入参数5 14 #此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo 15 # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数 16 demo = outer(5) 17 # 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量 18 # demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数 19 demo() # 15 20 21 demo2 = outer(7) 22 demo2()#17
来源于:https://www.cnblogs.com/Lin-Yi/p/7305364.html
2.递归函数 ?
如果一个函数在内部直接或者间接调用自身, 这个函数就是递归函数.
递归的最大层数 998
递归函数特性:
必须有一个明确的结束条件;
每次进入更深一层递归时,问题规模相比上次递归都应有所减少
相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入).
递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧.
由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
# 循环方式 def sum_cycle(n): sum = 0 for i in range(1,n+1) : sum += i print(sum) # 递归方式 def sum_recu(n): if n>0: return n +sum_recu(n-1) else: return 0 sum_cycle(100) sum = sum_recu(100) print(sum) 结果: 5050 5050
https://blog.csdn.net/ruanxingzi123/article/details/82658669
3. python装饰器 ?
装饰器本质上是一个Python函数.
在不改变源代码,不改变调用方式的情况下给其他函数或者类添加额外的功能. 装饰器的返回值也是一个函数对象。
应用场景:插入日志、性能测试、事务处理、缓存、权限校验等。有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续复用。
根据函数是否传参 是否有返回值 ,可以分析出装饰器的四种形式:
形式一:无参无返回值
1 def outer(func):
2 def wrapper():
3 print("装饰器功能1")
4 ret = func()
5 print("装饰器功能2")
return ret
6 return wrapper
7
8 # 定义一个无参无返回值的函数
9 @outer
10 def main_func():
11 print("hello")
12
13 main_func() # 开始执行
14
15
16 结果如下:
17 装饰器功能1
18 hello
19 装饰器功能2
总结: 装饰器功能1 装饰器功能2 可以根据具体项目需求需要的附加功能来写具体代码,可以在原功能函数之前,也可以在其之后
形式二:无参有返回值
1 def outer(func):
2 def wrapper():
3 print("装饰器功能1")
4 ret =func()
5 print("装饰器功能2")
6 return ret
7 return wrapper
8
9 # 定义一个无参有返回值的函数
10 @outer
11 def main_func():
12 return "hello"
13
14
15 print(main_func()
16
17
18 结果如下:
19 装饰器功能1
20 装饰器功能2
21 hello
总结: 装饰器功能1 装饰器功能2 可以根据具体项目需求需要的附加功能来写具体代码,可以在原功能函数之前,但不能在原功能函数之后
形式三:有参无返回值
1 def outer(func): 2 def wrapper(str1): 3 print("装饰器功能1") 4 ret =func(str1) 5 print("装饰器功能2") 6 return ret 7 return wrapper 8 9 # 定义一个有参无返回值的函数 10 @outer 11 def main_func(str1): 12 print("hello "+str1) 13 14 15 main_func("Python") 16 17 18 结果如下: 19 装饰器功能1 20 hello Python 21 装饰器功能2
总结: 装饰器功能1 装饰器功能2 可以根据具体项目需求需要的附加功能来写具体代码,可以在原功能函数之前,也可以在其之后
形式四:有参有返回值
1 def outer(func):
2 def wrapper(str1):
3 print("装饰器功能1")
4 ret =func(str1)
5 print("装饰器功能2")
6 return ret
7 return wrapper
8
9 # 定义一个有参有返回值的函数
10 @outer
11 def main_func(str1):
12 return "hello "+str1
13
14
15 print(main_func("Python"))
16
17
18 结果如下:
19 装饰器功能1
20 装饰器功能2
21 hello Python
总结: 装饰器功能1 装饰器功能2 可以根据具体项目需求需要的附加功能来写具体代码,可以在原功能函数之前,但不能在原功能函数之后
万能装饰器:
def wrapper(func): # func为被装饰函数
def inner(*args,**kwargs):
"""被装饰函数前需要添加的内容"""
ret=func(*args,**kwargs) #被装饰函数
"""被装饰函数后需要添加的内容"""
return ret
return inner
-
*args :按照位置传值,多余的参数都给args,以元祖的形式存储
-
**kwargs :按照关键字传值,多余的参数个kwargs,以字典的形式存储
4.可迭代对象、迭代器、生成器?
Python可迭代对象(Iterable)
Python中经常使用for
来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象,像常见的list
, tuple
都是。如果给一个准确的定义的话,就是只要它定义了可以返回一个迭代器的__iter__
方法,或者定义了可以支持下标索引的__getitem__
方法,那么它就是一个可迭代对象。
可迭代对象与迭代器
- 可迭代对象包含迭代器。
- 如果一个对象拥有
__iter__
方法,那么它是可迭代对象;如果一个对象拥有next
方法,其是迭代器。 - 定义可迭代对象,必须实现
__iter__
方法;定义迭代器,必须实现__iter__
和next
方法。
-
_iter_()
该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法 -
next()
返回迭代的每一步,实现该方法时注意要最后超出边界要抛出StopIteration异常。
迭代器Iterator
迭代器就是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()
函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。
实际上,在使用next()
函数的时候,调用的就是迭代器对象的__next__
方法
so 我们要想构造一个迭代器,就要实现它的__next__
方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现__iter__
方法,而__iter__
方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的__iter__
方法返回自身即可。
一个实现了__iter__
方法和__next__
方法的对象,就是迭代器。
生成器 :
- 生成器是一种特殊的迭代器,生成器
自动
实现了“迭代器协议”(即__iter__
和next
方法),不需要再手动实现两方法。 - 生成器在迭代的过程中可以改变当前迭代值,而修改普通迭代器的当前迭代值往往会发生异常,影响程序的执行。
- 具有
yield关键字
的函数都是生成器,yield
可以理解为return
,返回后面的值给调用者。不同的是return
返回后,函数会释放,而生成器则不会。在直接调用next
方法或用for语句进行下一次迭代时,生成器会从yield下一句开始执行,直至遇到下一个yield