1.装饰器
原因:“开放封闭”:对扩展开发;对已实现的功能封闭
含义:不修改原函数的前提下,增加函数的功能,只能在函数运行前或者运行后添加。
#基本结构
def check_logic(fun):
def inner():
#动作1
#动作2
fun()
return inner
@check_logic #即:f1=check_logic(f1)
def f1():
print("hello")
#带多个参数的装饰器
def xxx(func):
def yyy(*args,**kwargs):#用来接收不确定个数的参数
ret=func(*args,**kwargs)#将接收到的参数进行拆包,传递到原函数中
return ret
return yyy
@xxx
def a(num):
print("___1",num)
return 100,200,300
@xxx
def b():
print("-----2")
print(a(100))
#带有多个参数的类装饰器
class Test(object):
def __init__(self,num):
print("___init")
self.__num=num
def __call__(self,func):
#类中带有__call__,可以对实例对象直接调用:实例对象(参数)
print("__call")
self.__func=func
return self.call_old_func
def call_old_func(self):
print("___功能1")
self.__func()
print("__功能2")
@Test(100)
def a():
print("___test")
print(a())
参考:
https://www.bilibili.com/video/BV1Pu411v7zb?p=15
2.闭包
什么是闭包?
1.函数A中嵌套定义了函数B,且函数B用到了函数A的变量或者形参,那么函数B及函数A中的变量或者形参称之为闭包。外部函数返回内部函数的引用
def counter(start=0):
def add_one():
nonlocal start#添加nolocal 可以让外部变量在闭包的内部函数中进行修改
start+=1
return start
return add_one
c1=counter(5)#创建一个闭包
print(c1())#相当于:print(counter(5)())
c2=counter(20)#创建另一个闭包
print(c1()) #闭包不会释放变量,会永久储存
print(c2())
# 1.闭包的格式
# 2.闭包不会释放变量,会永久储存,占用存储空间
# 3.nonlocal的用法
# 4.对象:N个属性+N个函数;
# 闭包:N个属性+一个函数(一般来讲)
3.迭代器:对可迭代对象进行记录的方式。
# 1.迭代器与可迭代对象
num=[11,2,33,44,55] #可迭代对象:能用for循环遍历的
num_iter=iter(num) #取num这个可迭代对象的迭代器
num1=next(num_iter) #提取迭代器的下一个数据
print(num1)
for n in num:
print(n)
#for循环可以过程可以通过iter()和next()函数来实现
#即:先调用iter(),将num当作实参,得到num的迭代器
# 再调用next(),对迭代器进行取值
# 2.迭代器中异常StopIteration的处理
num=[11,2,33,44,55] #可迭代对象:能用for循环遍历的
num_iter=iter(num) #迭代器
while True:
try:
n=next(num_iter)
print(n)
except StopIteration as ret:
print(ret)
break
# 3.自定义可迭代对象和迭代器
class My_list(object):
def __init__(self):
self.items=[]
def add(self,val):
self.items.append(val)
def __iter__(self):
# 1.标记当前类创建出来的对象一定是 可迭代对象
# 2.当调用iter()函数的时候 这个方法会被自动调用,返回它自己指定的那个迭代器
return MyIterator()
class MyIterator(object):
def __init__(self):
pass
def __next__(self):
# 1.标记当前类创建出来的对象一定是 迭代器
# 2.当调用next()函数的时候 这个方法会被自动调用,返回一个数据
pass
def __iter__(self):
pass
mylist=My_list() #可迭代对象
mylist.add(5)
mylist.add(11)
mylist.add(90)
mylist.add(44)
mylist_iter=iter(mylist.items) #生成迭代器
print(next(mylist_iter))
# >>5
4.生成器
Python中,一边循环一边计算的机制,称为生成器:generator。
# 1.创建生成器的方式1:将列表的[]改为()
nums=[x for x in range(5)]#列表
print(nums)
#[0, 1, 2, 3, 4]
nums1=(x for x in range(5))#生成器:只记录生成数据的方式,而不是事先存储这些数据(一般用于数据不确定时)
print(nums1)
#<generator object <genexpr> at 0x000001EA195C14F8>
# 2.创建生成器的方式2:函数定义中包含yield关键字
def fib_generator():
num1=1
num2=1
while True:
temp_num=num1
num1,num2=num2,num1+num2
yield temp_num
fib=fib_generator() #如果一个函数中有yield,那么fib_generator()就变成了创建一个生成器对象
print(fib) #<generator object fib_generator at 0x0000019550D314F8>
#通过next函数调用
num1=next(fib)#把yield关键字后的数值 temp_num 返回,当作next()的返回值
print(num1)#1
num2=next(fib)
print(num2)#1
num3=next(fib)
print(num3)#2
# yield关键字
# 1.只有有yield关键字,虽然是调用函数,但实际上是创建了一个生成器对象
# 2.通过next调用生成器,可以让带有 yield 的 def 的代码块开始执行
# a.在每次调用next()的时候执行,遇到yield语句返回,把yield关键字后的数值返回,当作next()的返回值
# b.再次执行时从上次返回的yield语句处继续执行,直到遇到下一次yield为止,把yield关键字后的数值返回,当作next()的返回值
# 3.函数中既有 yield,又有return
def fib_generator():
num1=1
num2=1
temp_num=num1
num1,num2=num2,num1+num2
yield temp_num
temp_num=num1
num1,num2=num2,num1+num2
yield temp_num
temp_num=num1
num1,num2=num2,num1+num2
yield temp_num
return "3个斐波那契数列"
fib=fib_generator() #如果一个函数中有yield,那么fib_generator()就变成了创建一个生成器对象
num1=next(fib)
print(num1)#1
num2=next(fib)
print(num2)#1
num3=next(fib)
print(num3)#2
#
#把return的数值用 异常 暂时存储起来
num4=next(fib)
print(num4) #StopIteration: 3个斐波那契数列
try:
print(next(fib))
except StopIteration as ret:
print(ret.value) #有return,封装到异常对象的value值中