手把手教你学python第十六讲(魔法方法收尾和练习)

8 篇文章 0 订阅
5 篇文章 0 订阅

图片出不来请到https://www.bilibili.com/read/cv328084

经过重重艰难,终于来到了魔法方法。我先预告一下,后面就是爬虫了。加油。推荐一个总结的比较好的内置函数的中文网站http://www.cnblogs.com/sesshoumaru/category/894935.html。现在网上的python教程真的是铺天盖地,那么我建议你只要下定决心学python了,当然现在最好学3,因为2.7很快就不更新了,还有就是选定一个教程就从头到尾坚持跟。

迭代器

参考了https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143178254193589df9c612d2449618ea460e7a672a366000和

http://python.jobbole.com/81916/以及http://blog.chinaunix.net/uid-15174104-id-4172583.html有很多改动和整合。

我们先来看两个概念,可迭代对象,我们称之为iterable。还有一个叫做迭代器,iterator。

我们可以通过下面的代码来判断一个对象是不是iterable

看来我们所有的容器类型都是iterable的。那么它们是不是iterator呢?

它们都不是Iterator唉,但是iter()以后,就变成了Iterator了,是不是很神奇。下面我们要探究到底什么区分开了iterable和iterator。什么是iterable的呢?就是具有__iter()__魔法方法的对象。iterator是具有__iter__和__next__的对象,那么首先就不可避免的说到了iter()和next()两个函数。关于这里魔法方法的自动调用应该不用重复了吧

iter(a)就是自动调用a.__iter__,next()一样。


next()就是一个一个数据发送出来,直到后面没有数据了,就会报StopItration的异常。当然你还可以设置返回的内容


我这里就只展示一下list类型,其它的容器类型都是一样的。还有些对象没有__iter__方法,不是iterable

其实python上面的判断是类似于一种傻瓜判断,有__next__方法和__iter__的类的就是按照上面的判断方法就被判断成是it,我们完全可以自己胡乱定义一个类。

下面这张图是说明__iter__的必要性。

当然这是我们自己没事干在这里乱写魔法方法而 没有任何功能实现。python自己是没有这么闲,它们内部写好的这些列表,元组等类型的魔法方法内部都是有语句,可以实现一定的功能的,python开发人员都封装好了,我么还可以猜测iter()的实质就是加一个__next__魔法方法而已。下面我们来深层次探究一下iterable和iterator之间的关系,其实从上面的定义就知道,没错,Iterator是Iterable的子类,并且它实现了__next__魔法方法。iterable需要__iter__来产生iterator,而iterator需要通过__new__来实现迭代。

你是不是认为,上面的定义其实说起来就一句话iterable的其实就是你比较懒没有写__next__方法而已嘛,你要是勤劳一点,都写上__next__方法,那还哪有iterable呢?唉,不要急,存在即合理。看完下面这段代码,你会明白为什么都要存在

看出区别了吗?你说我看到第二次for i in b什么都没有打印,但是也没有什么用啊,不知道这能得出什么结论啊,这是因为我们不了解for。下面我们就来说for其实做了一件什么事

注意看结果a,b,c的位置,__iter__里面返回self是因为它自己就有__next__方法,已经是迭代器了

我前面没有加限制条件,你可以自己加的,可以在for循环里加,很简单我就不演示了

for相当于自动会调用iter()先生成一个iterator,然后通过next每次打印出来一个数据。这里回到上面我们看到a=[1,2,3]我们两次对a进行迭代,都没有问题,但是对b=iter(a)进行两次for循环迭代操作第二次什么都没有打印,为什么?不知道你们有没有联想到以前的文件指针。这里的迭代器iterator也有一个类似的指针,当迭代一次以后就指向了末尾,再进行迭代就什么都不发生,但是对于iterable对象没有这个问题,它每次相当于有一个自动回到开头的功能,使得iterable是可以反复利用的,而iterator则可以比喻成一个一次性用品。当然由于iterator是通过iter(iterable)来得到的,你可以重复iter得到多个iterator,这样就可以重复利用了。

那么有没有一种不需要iter内置函数的转换就直接是iterator呢?是有的,这就是我们下面要讲的很重要的一个概念

生成器

参考了http://bbs.fishc.com/thread-56023-1-1.html

回想前面我们所说的函数有关的一些说法,函数里的变量都是局部的,除了你用global或者nonlocal,又或者你用的是容器类型。局部变量有什么特征呢?就是调用结束,如果没有指针指向它,这个函数就会被初始化,这很好理解是吧。但是我为什么说没有指针指向它呢?是因为还有一个叫做闭包的一个东西。我们来看一段代码,我不会细讲,因为这都是以前的知识

我们曾经还说过,函数都是有返回值的,如果没有return语句会自动返回None,并且python不能有多个返回值,但是可以返回一个容器类型哈,相当于变相返回了容器里的多个值,还有一点函数内只要执行到return语句(或者有异常)就会返回,不会执行会面的语句。这些以前我都用大量代码验证过了。下面我们就来看看用yield的生成器函数有什么不同。这种生成器在其它语言里也叫做协同程序。

对比下面的一般函数和带yield的函数

这里呢我更加倾向于把yield理解为一种中断式返回,什么意思呢?就是在函数里一旦遇到了yield,它会和遇到return一样返回,不同的是中断返回是保护了断点的,什么叫做保护了断点呢?就是说我就相当于看视频的暂停,我可能要去上厕所,我先暂停一下,回来我继续去厕所的时候看到的位置看,而不是从头看。然后呢,我们来看一看a1是不是生成器,注意看a1是有__next__和__iter__方法的。

所以说用next来调用也可以理解。当然你可以隐藏next,也很简单,就是用for

注意下面这种情形,结合前面说的yield是一种特殊的return,还有前面复习过的return应该可以理解,因为return是没有保护断点的,直接return就直接相当于关掉了视频了,就结束了,或者按照官方一点的话话说控制权已经完全交出去了。这种用yield的函数生成器上面说过也是iterator,所以也是一次性的,也可以通过类似于新建类实例的方法一样重复使用。

一般我们是配合while语句来使用这种函数处理无限序列。不是所有的类都能处理无限序列的,iterator是一个,上面的闭包也可以。


你可以自己在for里限制条件,产生有限的项

当然你还可以这么改

不知道还有没有人记得前面讲过一个东西,叫做列表推导式,我们来看一看,看下面,你会发现集合,字典都是有推导式的,但是字符串和元组没有

实际上我们小括号括起来的看到了吗?是一个生成器generator。python设计的生成器是可以直接这么写的。那么同样它也是有一次性的问题。

下面我们就要做一些练习,练习是很重要的,绝对不能眼高手低,万事开头难,但是一旦你下定决心开始写代码,并且愿意花费时间去钻研代码,一定会在量变的积累下形成质变。重在坚持。

练习(其实同时也在复习前面的知识,还有综合运用前面的知识)




其实也是完全没有问题的,为什么呢?因为python的自动回收机制,当没有指针指向这个文件的时候文件会自动被关闭。但是为了保险起见,我们还是要随后关掉文件,如果你身边有程序员就会发现他们有个习惯,习惯性按Ctrl+S,不信你去观察一下,还有一种方法是什么呢?回忆一下,没错,就是with,如果你不熟悉with请回去复习一下了。




先来学习一下ord(),就是返回一个字符的ASCII码



3

注意是所有子字符串,但是这道题并不难


4

我们这里就写一个循环进位的


5



如果我们只要求在Nstr类里计算,那么我们会有更简单的处理办法


6



7

继承上一题的思想


8



9


这道题很简单,可能你会疑惑__setattr__我们并没有写啊,为什么可以赋值?其实很简单Demo的基类Object是有__setattr__的。

10.编写一个Counter类,可以返回实时对象有几个绑定属性



11




12





13



14






15



16




其它的功能请自己去试

17



18

注意看要求是不一样的,还有处理的是有顺序的序列,这样很好理解,不是序列根本没有索引。


19

提示一点,不要想用一个列表去存素数,这样你的内存会被挤爆。根据素数定理不精确的估计这个数有2e6/(ln(2e6))=137849,也很大对吧。这个我们其实也很容易迭代实现


一共有148933个素数,比估计的还大,这很正常,素数定理只是一个概率估计。那么现在我要求必须用生成器实现。就是这样子,只是为了做练习而已。

代码链接:https://pan.baidu.com/s/1LqBGwIs1wgabveP6rHLhew 密码:enk7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值