有了前面的基础,其实掌握的比较扎实的话还是能够做出一些简单的东西的,至少解决一些个基本的数学题还是问题不大,比如说实现一个斐波那契数列,杨辉三角什么的。多数情况下使用循环 for ... in 或者 while 再加上 if 等就能够实现些很复杂的程序了。
接下来这部分内容的主要功能是为了简化循环而存在的,也秉持着python编程的一个原则:能一条代码解决的事儿决不写两条。就这样!
1,切片
切片,从字面上理解意思应该差不多能够到位。就是从一个大块儿中切出来一片或者一块儿。这个大块儿的东西,在程序中可以是列表,元组,集合,字典,字符串等。
举个例子,比如说从一个含有5个元素的列表中取出前三个元素,该怎么实现?
如果没学切片之前,可以用循环实现,就像这样:
但是如果使用python的切片操作,则很简单,就像是这样:
可以看到,python的切片操作符使用的是“[start:end]”,start 和 end 均表示元素的索引,获取到的元素在 [start, end) 之间,就是说包含 start 而不包含 end,如果你不指定 end 那么默认就切到结尾。
通过切片操作对列表,元组等数据结构进行操作之后返回的数据类型和原数据类型相同。
以上就是关于切片操作的基本介绍,当然,这也是它的全部。
那切片操作通常适用的场景就是,你希望可以快速的从一个列表或者什么中获取其中的一部分,那么用切片操作是最合适不过了!
当然了,切片操作还支持“倒着切”和对字符串进行切割。所谓的“倒着切”是因为,不管是列表还是元组,它们最后一个元素的索引在python中“规定为 -1”,那倒数第二个元素就是“-2”以此类推。
一个问题:切片可以对集合或者字典进行切割吗?解释一下原因。
2,生成式
生成式是另外一种操作。切片的目的是从过一个已有的列表中切出一部分返回,而生成式的目的则是从无到有的构建一个列表。
一个案例:假如我准备构建一个含有10个元素的列表,可以怎么做?
这里,可以利用python的一个内置函数xrange来生产一些数字,然后利用循环填充到一个列表中。
那么使用生成式应该怎么实现呢?我还是画(截)个图来看看:
效果一样,但是代码是不是少了很多。这就是python的编码原则,尽可能的少写代码!
同时呢,生成式还可以像for一样支持嵌套,当然了,不只是一级嵌套,同样也支持多级,不过通常情况下最多也只能用到二级了吧。以下的例子,使用生成式来生成两个字符串的全排列:
通过上面的两个例子,想必你已经看到了生成式的运行过程了吧?
对,就是你所想的那样,不要疑惑,记住它,在你以后的python路上这个会有很大的帮助!
注意:由于生成式只能采用“[]”这种方式,所以只能生产“list”类型的数据结构,所以生成式,通常情况下我们称之为:列表生成式。
补充:其实还可以生成集合,只需要把“[]”替换成“{}”
一个问题:上面的两句话矛盾吗?
3,生成器
如果你理解了生成式,那么对于生成器来说你只需要懂一点,那就是在生成式满足不了你的时候, 你可以考虑使用生成器。
所以生成器是生成式的加强版,注意:不是替代版!
一个案例:构建一个斐波那契数列数列的列表
方案一:采用循环的方式
由于在python中支持同时给多个变量赋值,所以代码可以简化成这样:
这里,简化之后的代码,最妙的一点我认为在于:在其它编程语言中,如果要做到两个变量的交换,那么一定需要引入中间变量,但是在python中利用“赋值符号 =”支持多赋值的机制可以很容易的避免这个问题。
上例中只是采用基本的python编程方法实现了我们的要求,但是这里能不能采用生成式来实现呢?
答案是可以的!
方案二:采用生成器
有些生成式的逻辑太过于复杂,导致我们没办法直接通过生成式来完成,这个时候可以借助于函数来完成复杂的逻辑,然后把函数转换成生成器,这样我们就可以“迭代”生成器来“模拟生成式”生成我们需要的列表。
那么在这里,把普通函数转换成生成器需要借助一个关键字“yield”。
它的作用是中断操作并返回,当下次再调用“next”方法的时候或者迭代的时候,从中断出继续执行,比如这样:
那现在,对于生成器,是不是有了一个大概的影响呢?
其实还一个问题,我说生成器是作为生成式的加强版,那么是不是应该生成式具有的功能,生成器同样应该具有呢?
就比如我们说生成式的时候的第一个案例,生成一个含有10个元素的列表,如果用生成器应该怎么实现?
可以看到,生成器和生成式,构建的方法的区别在于一个才用的是“[]”而一个采用的是“()”
同时对于生成器,如果你想构建一个列表,那么后期必须要通过“迭代”来实现,而生成式则可以直接实现。
同时,由于生成器的特殊性,导致如果你想访问生成器中的各个元素,则需要调用它的“next”方法。
以上就是对于生成器全部介绍。
经过仔细思考,对比之后,你就会有下面的一些总结:
对于生成式,它很局限,只能够帮助你快速的生成列表,而对于生成器,由于后期元素的访问必须要通过“迭代”,那么“迭代”出来的元素可以放到列表中,也可以放到集合、元组、字典中,所以采用生成器对于最终构建出来的数据类型没有限制。
那采用生成式还是生成器,这个就需要根据情况来自行决定了!
4,补充:迭代
什么叫迭代?说白了就是做循环,而且还是采用for ... in 这种循环结构。这就叫“迭代”!
上面这个,是我们经常用,也是一种最简单的迭代。
同样,我们也可以迭代字典:
默认情况下,迭代字典,迭代的是key,如果你想迭代value,你可以这样:采用 “itervalues”方法
当然,如果你想既迭代key也迭代value,那你可以这样:
然后,我们来看看 “iteritems”这个方法得到的数据类型:
看懂了这个类型,然后再看一个案例:
这样,你对迭代是不是就已经很清楚了呢?^_^
有了迭代的基础,再想想,我们的生成式和生成器,它们的内部不是也应用到了 for ... in 这种结构吗?于是下面这样子的代码你还看不懂吗?
O(∩_∩)O哈! 真是有趣,在python中,你可以尽情的把你的代码写的“高大上”一些,而且这也正是python所推荐你这么做的!
---------------------------------------------------华丽的分割线---------------------------------------------
切片,生成式,生成器,迭代,作为前面对python扩展数据结构的操作的一些补充说明,在今后的python编程中应用会非常频繁,所以一定要理解透彻,这样才能编写出“高大上”的代码嘛 ^_^