迭代器、闭包、装饰器、为对象动态添加属性或方法、__slots__、生成器
迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
1. 可迭代对象
以直接作用于 for 循环的数据类型有以下几种:
一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。
2. 判断是否可以迭代
可以使用 isinstance() 判断一个对象是否是 Iterable 对象:
In [50]: from collections import Iterable
In [51]: isinstance([], Iterable)
Out[51]: True
In [52]: isinstance({}, Iterable)
Out[52]: True
In [53]: isinstance('abc', Iterable)
Out[53]: True
In [54]: isinstance((x for x in range(10)), Iterable)
Out[54]: True
In [55]: isinstance(100, Iterable)
Out[55]: False
而生成器不但可以作用于 for 循环,还可以被 next() 函数不断调用并返回下一个值,直到最后抛出 StopIteration 错误表示无法继续返回下一个值了。
3.迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
In [56]: from collections import Iterator
In [57]: isinstance((x for x in range(10)), Iterator)
Out[57]: True
In [58]: isinstance([], Iterator)
Out[58]: False
In [59]: isinstance({}, Iterator)
Out[59]: False
In [60]: isinstance('abc', Iterator)
Out[60]: False
In [61]: isinstance(100, Iterator)
Out[61]: False
4.iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
In [62]: isinstance(iter([]), Iterator)
Out[62]: True
In [63]: isinstance(iter('abc'), Iterator)
Out[63]: True
总结
- 凡是可作用于 for 循环的对象都是 Iterable 类型;
- 凡是可作用于 next() 函数的对象都是 Iterator 类型
- 集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象。
from collections import Iterable from collections import Iterator #判断是否可迭代 print("[]isinstance",isinstance([], Iterable)) print("{}isinstance",isinstance({}, Iterable)) print("abc isinstance",isinstance("abc", Iterable)) print("range isinstance",isinstance((x for x in range(10)), Iterable)) #判断是否是可迭代对象 print("[]isinstance",isinstance([], Iterator)) print("{}isinstance",isinstance({}, Iterator)) print("abc isinstance",isinstance("abc", Iterator)) print("range isinstance",isinstance((x for x in range(10)), Iterator)) #用iter 转化为可迭代对象 print("[]isinstance iter()",isinstance(iter([]), Iterator)) print("{}isinstance iter()",isinstance(iter({}), Iterator)) print("abc isinstance iter()",isinstance(iter("abc"), Iterator)) print("range isinstance iter()",isinstance((x for x in range(10)), Iterator))
闭包
程序:
def test(num): print("-------1--------") def test_in(number): print("-------2--------") print(num+number) print("-------3---------") return test_in ret=test(100) ret(3) ret(2) ret(1)
运行结果:
-------1--------
-------3---------
-------2--------
103
-------2--------
102
-------2--------
101
装饰器
def w1(func): def inner(): print("----验证----") func() return inner def f1(): print("----f1----") def f2(): print("----f2----") t=w1(f1) t() f1=w1(f1) f1()
改进:
def w1(func):
def inner():
print("----验证----")
func()
return inner
@w1 #等价于 f1=w1(f1)
def f1():
print("----f1----")
@w1 #等价于 f2=w2(f2)
def f2():
print("----f2----")
f1()
f2()
两个装饰器:
def add_p(func):
def inner():
print("add_p")
return "<p>"+func()+"</p>"
return inner
def inner():
print("add_p")
return "<p>"+func()+"</p>"
return inner
def add_t(func):
def inner():
print("add_t")
return "<t>"+func()+"</t>"
return inner
@add_p
@add_t
def test():
return "hello world"
print(test())
通用装饰器:
def func(functionName):
def func_in(*args,**kwargs):
print("---func_in---")
ret=functionName(*args,**kwargs)
return ret
return func_in
def func_in(*args,**kwargs):
print("---func_in---")
ret=functionName(*args,**kwargs)
return ret
return func_in
@func
def test1():
print("test1")
return "test1"
print(test1())
def test1():
print("test1")
return "test1"
print(test1())
@func
def test2(str):
print("test2=(%s)"%str)
test2('fwfwe')
def test2(str):
print("test2=(%s)"%str)
test2('fwfwe')
为对象动态添加属性或方法
a=100 def test(): print("---test") test() a=test a() class Test(object): pass t=Test() print(dir(t)) class Person(object): def __init__(self,name,age): self.name=name self.age=age def eat(self): print("%s正在吃"%self.name) laowang=Person("laowang",23) print(laowang.name) print(laowang.age) laowang.addr="北京" print(laowang.addr) laozhao=Person("laozhao",32) #print(laozhao.addr) #没有给类添加属性,失败 #给类添加属性 Person.num=100 print(laowang.num) print(laozhao.num) laowang.eat() def run(self): print("%s正在跑"%self.name) #laowang.run() #为实例老王添加方法run import types laowang.run=types.MethodType(run,laowang) laowang.run() xxxx=types.MethodType(run,laowang) xxxx() #类动态添加静态方法 @staticmethod def test(): print("----staticmethod----") Person.test=test Person.test() # 添加类方法 @classmethod def printNum(cls): print("----class method----") Person.pNum=printNum print(Person.pNum())
__slots__ 使用
class Person(object): __slots__=("name","age") #限定属性 def __init__(self,name,age): self.name=name self.age=age def show(self): print("姓名是%s,年龄是%d"%(self.name,self.age)) p=Person("张三",35) p.show() p.sex="男" #添加属性失败
生成器
#生成器产生原因 l=[x*2 for x in range(10000000000)] print(l) #生成器用法一 b=(x*2 for x in range(10)) print(b) print(next(b)) print(next(b)) print(next(b)) #生成器用法二 def creatNum(): print("start") a,b=0,1 for i in range(10): temp=yield b if temp is not None: print(temp) a,b=b,a+b print("stop") n=creatNum() print(next(n)) print(n.__next__()) n.send("nihao") # 和next功能一样,往yield传递一个返回结果 for i in n: print(i) #生成器用法三 协程 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__()
浙公网安备 33010602011771号