Python入门(简明Python教程)——酉(生成器和迭代器)

python零碎的注意

返回多个值/返回元组

a=1
b=2
a,b=b,a
print(a,b)

结果:

2 1

lambda表格即为一种临时使用的匿名函数,你懒得再写一个函数而使用的。一般来说应为比较简单的函数(当然你也可以用lambda表格写一个复杂的函数,但这样并不推荐。)

 

列表推导:

listone=[2,3,4]
listtwo=[2*i for i in listone if i>2]
print(listtwo)

结果:

[6, 8]

 

断言:

mylist=['item']
assert len(mylist)>=1
mylist.pop()
assert len(mylist)>=1

结果:

Traceback (most recent call last):
  File "C:/Users/baili/PycharmProjects/new/base.py", line 37, in <module>
    assert len(mylist)>=1
AssertionError

函数加不加括号:

函数不加括号仅有函数名表示该函数的地址,加括号表示函数。

把函数赋值给一个变量时不加括号即把函数关系赋给变量,可以把新的变量直接当函数使用。而此时加括号则新变量不能当函数使用了,即使括号内并没有需要的参数也不能当成函数使用。在使用isinstance函数判断Iterable时也要加了括号的可迭代函数才能返回true,否则不带括号即使是可迭代函数也依然返回false。

def add(x,y):
    print(x+y)

q=add
q(3,4)
w=add()
w(3,4)

结果:

7
Traceback (most recent call last):
  File "C:/Users/baili/PycharmProjects/agrith/iterable.py", line 22, in <module>
    w=add()
TypeError: add() missing 2 required positional arguments: 'x' and 'y'

另:

from collections import Iterable

print(isinstance([],Iterable))

class Mylist(object):
    def __init__(self):
        self.list=[]
    def add(self,item):
        self.list.append(item)
    def __iter__(self):
        pass

mylist=Mylist()
print(isinstance(Mylist,Iterable))
print(isinstance(Mylist(),Iterable))
print(isinstance(mylist,Iterable))

结果:

True
C:/Users/baili/PycharmProjects/agrith/iterable.py:1: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
  from collections import Iterable
False
True
True

self即c中的this指针

 

items()方法:

dic={'a':1,
     'b':'rang',
     'c':6}

#print(items(dic))
print(dic.items())

注释掉的部分是思想出现了问题,没有认识到python是面向对象的。items()方法是字典的

结果:

dict_items([('a', 1), ('b', 'rang'), ('c', 6)])

自定义可迭代类:

class Mylist(object):
    def __init__(self):
        self.items=[]
        self.current=0

    def add(self,val):
        self.items.append(val)

    def __next__(self):
        if self.current<len(self.items):
            item=self.items[self.current]
            self.current+=1
            return item
        else:
            raise StopIteration

    def __iter__(self):
        return self

if __name__=='__main__':
    mylist=Mylist()
    mylist.add(1)
    mylist.add(2)
    mylist.add(3)
    mylist.add(4)
    mylist.add(5)
    for num in mylist:
        print(num)

可迭代对象本身就是一个迭代器(iterater)。迭代器需要'__iter__'方法和'__next__'方法,以此满足迭代器协议(__next__())和可迭代协议(__iter__())。

_xxx   :保护变量,意思是只有类对象和子类对象能够访问到这些变量(尽量避免在类外部直接修改)

__xxx__ :系统定义名字

__xxx  :类中的私有变量名

切片[10:]为后十个数

l=[]
for i in range(1,10):
    #l[i]=i*i
    l.append(i*i)
print(l)

注释部分思想出现了问题,python中的for循环抽象度很高,和c没有可比性。

列表生成式:

print([x*x for x in range(1,10)])
print([m+n for m in 'asd' for n in 'lkj'])

结果:

[1, 4, 9, 16, 25, 36, 49, 64, 81]
['al', 'ak', 'aj', 'sl', 'sk', 'sj', 'dl', 'dk', 'dj']

简化代码,但一般就用到二重循环,更高还是要写代码来循环。

生成器(generater):对比列表生成式就是把[]改为()即可,事实上,生成器是一种特殊的迭代器,因此在我们定义生成器的时候其实就隐式地实现了__iter__()方法和__next__()方法而不用我们自己显式地实现,说到底生成器只是为了方便我们迭代而出现的。

print((x*x for x in range(1,10)))
print((m+n for m in 'asd' for n in 'lkj'))

结果:

<generator object <genexpr> at 0x000002448C44B480>
<generator object <genexpr> at 0x000002448C44B480>

对比这两个结果易于发现不同。那么如果我们需要输出生成器中的每个元素,我们可以选择不断调用next()方法,但更常用的是在for循环中使用它,因为python中for循环结果是一种高度抽象的结构,它可以隐式地使用next()方法而输出每一个元素,显然for结构的代码会简单许多。

事实上,函数体中包含yield方法的即为生成器,它与普通的函数在执行的过程中有很大的不同。生成器函数中yield为返回指令而非return。且是挂起结果。

 

super()方法:就是一种在子类中调用父类的方法。

 

注意:

for count in [1:]:
    print(next(I))

错误,应为:

class Iter:
    def __init__(self):
        self.start=-1
    def __iter__(self):
        return self
    def __next__(self):
        self.start +=2
        return self.start
I = Iter()
for count in range(5):
    print(next(I))

结果:

1
3
5
7
9

上面这个为输出奇数的迭代器实现,下面给出生成器实现:

def odd():
    n=1
    while True:
        yield n
        n+=2
odd_num = odd()
count = 0
for o in odd_num:
    if count >=5: break
    print(o)
    count +=1

进一步学习迭代器:

class Counter:
    def __init__(self):
        self.index = 0

    def __next__(self):
        i = self.index
        if i < 10:
            self.index += 1
            return i
        else:
            raise StopIteration

counter = Counter()

for i in counter:
    print(i)

输出报错!因为此时你的的确确实现了一个迭代器,但这个迭代器自身不能迭代,因此这其实仅仅是一个迭代器但却没有任何用处。而造成这一错误的原因就是该段代码仅仅遵循了 迭代器协议(__next__()) 即这的的确确是一个迭代器,但却并没有遵循可迭代协议(__iter__())。因此它会报错。

改进后:

class Counter:
    def __init__(self):
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        i = self.index
        if i < 10:
            self.index += 1
            return i
        else:
            raise StopIteration

counter = Counter()
for i in counter:
    print(i)

输出结果:

0
1
2
3
4
5
6
7
8
9

在满足了迭代器协议(__next__())以及可迭代协议(__iter__())后输出正常。

“可迭代”和“迭代器”本身就是两码事。

事实上我们可以让普通的其他对象迭代而不一定非要是迭代器。

k=[1,2,3]
k.__next__()

报错,说明其实列表并不满足 迭代器协议,但我们清楚列表是可迭代的,满足可迭代协议。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值