qiaoliang0302

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

迭代器、闭包、装饰器、为对象动态添加属性或方法、__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 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

@func
def test1():
    print("test1")
    return "test1"
print(test1())

@func
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__()

 

posted on 2019-01-17 16:05  qiaoliang0302  阅读(158)  评论(0)    收藏  举报