迭代器
迭代:访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
1.可迭代对象
可以直接作用于for循环的数据类型,一类是集合数据类型,如list,tuple,dict,set,str等,一类是generator,包括生成器和带yield的generator function,这些对象统称为可迭代对象iterable
2.判断是否可迭代
用ininstance()判断一个对象是否是iterable对象。
from collections.abc import Iterator #3.8版本collection改为collection.abc
isinstance([1,2,3],Iterator)
iter()函数
把list、dict、str等iterable变成iterator可以使用iter()函数
isinstance(iter([]),Iterator)
闭包
#定义一个函数
def test(number):
#在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么僵这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数,number_in is %d"%number_in)
return number+number_in
#其实这里返回的就是闭包的结果
return test_in
闭包的应用
# def line_conf(a,b):
# def line(x):
# print(a*x+b)
# return line
# line1 = line_conf(1,1)
# line1(2)
# line1(3)
def createNum(a,b,x):
print(a*x+b)
a=1
b=1
x=0
creatNum(a,b,x)
#之前要看a*x+b,都得改
vim里面所有行添加注释 :%s/^/#/g 如果几行添加:1-14s/^/#/g
装饰器
程序开发经常会用到的功能,用好如虎添翼,面试必问。写代码遵循开放封闭原则,已经实现的功能代码不允许被修改,但可以被扩展。
@函数名是python的一种语法糖 有特殊功能
def w1(func):
print("---正在装饰---")
def inner():
print("---正在验证权限---")
func()
return inner
#只要python解释器执行到了这个代码,那么久会自动的进行装饰,而不是等到调用的时候再装饰
@w1
def f1():
print("---f1---")
def func():
print("----func--1---")
def func_in():
print("----func_in--1---")
ret = functionName()#保存返回来的haha
print("---func_in---2---")
return ret#把haha返回到17行处的调用
print("---func---2---")
return func_in
@func
def test():
print("---test---")
return "haha"
ret = test()
print("test return value is %s"%ret)
装饰器执行的时间
def w1(func):
print("---正在装饰---")
def inner():
print("---正在验证权限---")
func()
return inner
#只要python解释器执行到了这个代码就会自动进行装饰,而不是等到调用再装
@w1
def f1():
print("---f1---")
#调用F1之前已经进行装饰了
f1()
使用装饰器对无参数的函数进行装饰
def func(functionName):
print("---func---1---")
def func_in():
print("---func_in---1---")
functionName()
print("---func_in---2---")
print("---func---2---")
return func_in
@func
def test():
print("---test---")
test()
使用装饰器对有参数的函数进行装饰
def func(functionName):
print("---func---1---")
def func_in(a,b):#如果a,b没有定义,会导致16行的调用失败
print("---func_in---1---")
functionName(a,b)#如果没有把a,b当做实参传递,会导致调用12行函数失败
print("---func_in---2---")
print("---func---2---")
return func_in
@func
def test(a,b):
print("---test-a=%d,b=%d---"%(a,b))
test(11,22)
使用装饰器对不定长参数的函数进行装饰
def func(functionName):
print("---func---1---")
def func_in(*args,**kwargs):#如果a,b没有定义,会导致16行的调用失败
print("---func_in---1---")
functionName(*args,**kwargs)#如果没有把a,b当做实参传递,会导致调用12行函数失败
print("---func_in---2---")
print("---func---2---")
return func_in
@func
def test(a,b,c):
print("---test-a=%d,b=%d,c=%d---"%(a,b,c))
@func
def test2(a,b,c,d):
print("---test-a=%d,b=%d,c=%d,d=%d---"%(a,b,c,d))
test2(11,22,33,44)
使用装饰器对带有返回值的函数进行装饰
def func(functionName):
print("---func---1---")
def func_in():
print("---func_in---1---")
ret = functionName()#保存 返回来的haha
print("---func_in---2---")
return ret#把haha返回到17行处的调用
print("---func---2---")
return func_in
@func
def test():
print("---test---")
return "haha"
ret = test()
print("test return value is %s"%ret)
通用装饰器
def func(functionName):
def func_in(*args,**kwargs):
print("---记录日志---")
ret = functionName(*args,**kwargs)
return ret
return func_in
@func
def test():
print("---test---")
return "haha"
@func
def test2():
print("---test2---")
@func
def test3(a):
print("---test3-a=%d--"%a)
ret = test()
print("test return value is %s"%ret)
a = test2()
print("test return value is %s"%a)
test3(11)
带有参数的装饰器
def func_arg(arg):
def func(functionName):
def func_in():
print("---记录日志-arg=%s--"%arg)
if arg=="heihei":
functionName()
functionName()
else:
functionName()
return func_in
return func
#1. 先执行func_arg("heihei")函数,这个函数return的结果是func这个函数的引用
#2.@func
#3. 使用@func对test进行装饰
@func_arg("heihei")
def test():
print("---test---")
test()
#带有参数的装饰器,能够起到在运行时,有不同的功能
@func_arg("haha")
def test2():
print("---test2---")
test2()
作用域
命名空间 小二所在的班级
LEGB规则
locals -->enclosing function -->globals -->builtins
locals 当前所在命名空间(如函数、模块) ,函数的参数也属于命名空间内的变量
enclosing 外部嵌套函数的命名空间(闭包中常见)
def fun1():
a = 10
def fun2():
#a位于外部嵌套函数的命名空间
print(a)
globals,全局变量,函数定义所在模块的命名空间
a = 1
def fun():
#需要通过global指令来声明全局变量
global a
#修改全局变量,而不是创建一个新的local变量
a = 2
builtins,内建模块的命名空间
python在启动时会自动为我们载入很多内建的函数、类,比如dict,list,type,print都位于__builtin__模块中,可以用dir(__builtin__)查看
python动态添加属性以及方法
class Person(object):
def __init__(self,newName,newAge):
self.name = newName
self.age = newAge
laowang = Person("老王",1000)
print(laowang.name)
print(laowang.age)
laowang.addr = "北京..."#对象添加属性
print(laowang.addr)
laozhao = Person("老赵",18)
#print(laozhao.addr)
Person.num = 100#类添加属性
print(laowang.num)
print(laozhao.num)
添加方法
import types
class Person(object):
def __init__(self,newName,newAge):
self.name = newName
self.age = newAge
def eat(self):
print("---%s正在吃---"%self.name)
def run(self):
print("----%s正在泡---"%self.name)
p1 = Person("p1",10)
p1.eat()
#p1.run = run
#p1.run()#虽然p1对象中run属性已经指向10行的函数,但这句代码还不正确
#因为run属性指向的函数是后来添加的,并没有把p1当做第一个参数,导致第10行函数调用的时候,出现缺少参数的问题
p1.run = types.MethodType(run,p1)#函数名,实体对象,def run(self)把参数p1传进去run函数
#p1.run作为右边的返回值
p1.run()
添加静态方法
class Person(object):
def __init__(self,newName,newAge):
self.name = newName
self.age = newAge
def test():
print("---static method---")
Person.test = test
Person.test()
添加类方法
class Person(object):
def __init__(self,newName,newAge):
self.name = newName
self.age = newAge
def printNum(cls):
print("---class method---")
Person.printNum = printNum
Person.printNum()
__slots__的作用
为了达到限制的目的,python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性
class Person(object):
__slots__=("name","age")
P = Person()
P.name = "老王"
P.age = 20
P.score = 100
__slots__定义的属性仅对当前类实例起作用,对继承的子类不起作用
生成器
在python中,一边循环一边计算的机制,称为生成器generator
生成器的第一种方式
a = [x*2 for x in range(10)]#列表生成式
a = [x*2 for x in range(1000000)]#不想直接生成,保留计算方式,每用一个生成一个
b = (x*2 for x in range(10))#把列表生成式的【】换成()
b
next(b)#next()函数获得生成器的下一个返回值
第二种方式
def creatNum():
print("----start----")
a,b = 0,1
for i in range(5):
print("---1----")
yield b
print("---2---")
a,b = b,a+b
print("---3---")
print("---stop---")
a = creatNum()#creatNum()不会调函数生成,而是返回对象,需要找变量保存,生成器对象
for num in a:
print(num)
send
def test():
i = 0
while i < 5:
temp = yield i
print(temp)
i+=1
t = test()
t.__next__()
t.send("haha")#和next不同点,给yield i整个表达式一个结果,temp接收下次send发过来的值
t.__next__()
强调
上来就写t.send("haha"),要先调用t.__next__()或者先写t.send(None)
生成器完成多任务
多任务:协程、进程、线程 协程最快
def test1():
while True:
print("---1---")
yield None
def test2():
while True:
print("---2---")
yield None
t1 = test1()
t2 = test2()
while True:
t1.__next__()
t2.__next__()