zoukankan      html  css  js  c++  java
  • Python高级特性

    Python高级特性  切片  迭代  列表生成式  生成器

    一、切片

      切片:数据的分段切割。如下定义一个列表然后获取前五位数据。

      格式:对象[起始位置:需要读取的数量:间隔]

     1 >>> olist = list(range(10))
     2 >>>
     3 >>> olist
     4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
     5 >>> olist[0:5]
     6 [0, 1, 2, 3, 4]
     7 >>>
     8 >>> olist[0:5:2]
     9 [0, 2, 4]
    10 >>>

      定义并且声明一个olist列表对象,然后通过切片返回一个新的列表对象。其实位置默认是0,并且可以省略。如olist[:5]。间隔默认是1。

      range是一个系统函数,返回一个特定的有序的自然数,默认从零开始。

     1  1 >>> help('range')
     2  2 Help on class range in module builtins:
     3  3 
     4  4 class range(object)
     5  5  |  range(stop) -> range object
     6  6  |  range(start, stop[, step]) -> range object
     7  7  |
     8  8  |  Return an object that produces a sequence of integers from start (inclusive)
     9  9  |  to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.
    10 10  |  start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.
    11 11  |  These are exactly the valid indices for a list of 4 elements.
    12 12  |  When step is given, it specifies the increment (or decrement).
    13 13  |

      对于列表而言支持反向读取,如olist[-1],获取最后一条数据。那么对于切片slice而言是否支持???

    1 >>> olist = list(range(10))
    2 >>> olist[-2: -1]
    3 [8]
    4 >>> olist[-8: -1]
    5 [2, 3, 4, 5, 6, 7, 8]
    6 >>>
    7 >>> olist[-1]
    8 9
    9 >>>

       从测试结果来看是支持反向切片。但是反向之后切记最后一位角标是-1。

      之上的测试是对列表List进行的,那么我接下来看下对于String和tuple是否也适用!!!

    1 >>> oTuple = (1,2,3,4,5,6)
    2 >>> oTuple[0:5:2]
    3 (1, 3, 5)
    4 >>>
    5 >>>
    6 >>> str = 'abcdefg'
    7 >>> str[0:5:2]
    8 'ace'
    9 >>>

       从执行结果来看和我们的猜想是完全一致的。到这里可能有人会问了那么既然元组和列表及字符串都可以这么用,那么集合set和字典dict那???其实是不可以的,因为对于集合和dict而言是没有下标的。

     1 >>> oset = set([1,2,3])
     2 >>> oset
     3 {1, 2, 3}
     4 >>>
     5 >>> oset[0:2]
     6 Traceback (most recent call last):
     7   File "<stdin>", line 1, in <module>
     8 TypeError: 'set' object is not subscriptable
     9 >>>
    10 >>> odict = {'a:1','b:2','c:3'}
    11 >>> odict[0:2]
    12 Traceback (most recent call last):
    13   File "<stdin>", line 1, in <module>
    14 TypeError: 'set' object is not subscriptable
    15 >>>

     二、迭代

      迭代其实就是对集合<List, Tuple, dict, set等>的遍历。这里仅仅是列举了一些常见的集合,其实这里只要是Iterable的子类都可以使用迭代器来实现遍历。判断如下: 

     1 >>> oSet = set([1,3,4,5,])
     2 >>> oSet
     3 {1, 3, 4, 5}
     4 >>> for item in oSet:
     5 ...     print(item)
     6 ...
     7 1
     8 3
     9 4
    10 5
    11 >>> isinstance(oSet, Iterable)
    12 True
    13 >>> index = 2
    14 >>>
    15 >>> isinstance(index, Iterable)
    16 False
    17 >>>

       上述采用的是系统函数isinstance()完成对对象的判断,判断给对象是否是Iterable的子类。按照规定只要是Iterable的子类就可以直接使用for循环实现迭代。

      在使用isinstance方法时候判断是否是Iterable子类的时候,请记住请优先执行导入Iterable操作,默认isinstance方法是在collections类中。故而执行应该在文件头部增加from collections import Iterable。

      这里重点讲解下迭代器如何在迭代中获取index角标和dict遍历。

    1 >>> olist = ['A','B','C','E']
    2 >>> for index, item in enumerate(olist):
    3 ...  print(index, ' : ', item)
    4 ...
    5 0  :  A
    6 1  :  B
    7 2  :  C
    8 3  :  E
    9 >>>

      该出使用的系统方法enumerate(),该方法可以实现把集合变成角标-元素。

      字典集合遍历方式一获取key:

     1 >>> oDict = {'a:1','b:2','c:3'}
     2 >>>
     3 >>> oDict
     4 {'b:2', 'a:1', 'c:3'}
     5 >>>
     6 >>> for item in oDict:
     7 ...     print(item)
     8 ...
     9 b:2
    10 a:1
    11 c:3
    12 >>>

      字典集合遍历方式二获取value:

     1 >>> oDict = {'a':1,'b':2,'c':3}
     2 >>> oDict
     3 {'a': 1, 'b': 2, 'c': 3}
     4 >>> for value in oDict.values():
     5 ...     print(value)
     6 ...
     7 1
     8 2
     9 3
    10 >>>

      字典集合遍历方式三获取key-value:

    1 >>> oDict = {'a':1,'b':2,'c':3}
    2 >>> oDict
    3 {'a': 1, 'b': 2, 'c': 3}
    4 >>> for k, v in oDict.items():
    5 ...     print(k, " = ", v)
    6 ...
    7 a  =  1
    8 b  =  2
    9 c  =  3

    三、列表生成式

      列表生成式:顾名思义就是生成对应的列表。场景如定义一个自然数1-100放入到指定的集合等。使用方式就是使用系统函数range,前边已经关于这个方法有过说明,这里就直接跳过。

      range仅仅是获取有序的自然数,假如我们需求有天发生了变化,如获取1-100的平分数,然后放到指定集合,当下range就有点尴尬了。不过好在Python为我们做了这样的定制开发。一起走进代码。

    1 >>> oList = list(range(1,5))
    2 >>> oList
    3 [1, 2, 3, 4]
    4 >>>
    5 >>> nList = [x * x for x in range(1,5)]
    6 >>> nList
    7 [1, 4, 9, 16]
    8 >>>

      第一行到第四行是获取自然数1-5存放于指定集合。第五行到第七行是对自然数1-5开平方然后存放于指定集合中。

      上述内容细节还可以进一步优化,加入仅仅保留偶数的平方,那么我们可以这么干。

    1 >>> nList = [x * x for x in range(1,5) if x % 2 == 0]
    2 >>> nList
    3 [4, 16]
    4 >>>

      列表生成式实现排列组合,666。。。<又名for循环嵌套>

    1 >>> nList = [m + n for m in 'ADC' for n in 'MVP']
    2 >>> nList
    3 ['AM', 'AV', 'AP', 'DM', 'DV', 'DP', 'CM', 'CV', 'CP']
    4 >>>

      这里其实就是嵌套for循环。如何不理解可以换个方式去看。 

    1 >>> nList = []
    2 >>> for m in 'ADC':
    3 ...     for n in 'MVP':
    4 ...             nList.append(m + n)
    5 ...
    6 >>> nList
    7 ['AM', 'AV', 'AP', 'DM', 'DV', 'DP', 'CM', 'CV', 'CP']
    8 >>>

      看着这些代码是不是更好理解怎么肥事。

    四、生成器<Generator>

      生成器可以理解为对生成器的优化,这里优化主要是说在内存上的优化。举例子来说,假如需要数据有序的自然数零到一万存放于列表中,这时可以有两种方式,一是直接生成一刀一万的自然数放到内存中。另一种是用到那个就读那个到内存中。很显然第二种方式在内存这块要优于第一种,这就是我们要说的生成器。

      生成器声明格式和列表生成式大致相同,区别在于外围中括号和括号去别。看下生成器在代码中的使用,以及数据获取、

     1 >>> oGenerator = (n for n in range(1, 5))
     2 >>> oGenerator
     3 <generator object <genexpr> at 0x0000000002D60BF8>
     4 >>> next(oGenerator)
     5 1
     6 >>> next(oGenerator)
     7 2
     8 >>> next(oGenerator)
     9 3
    10 >>> next(oGenerator)
    11 4
    12 >>> next(oGenerator)
    13 Traceback (most recent call last):
    14   File "<stdin>", line 1, in <module>
    15 StopIteration
    16 >>>

       第一行创建了一个生成器对象。直接该对象。返回了个这'<generator object <genexpr> at 0x0000000002D60BF8>',What???一脸懵逼。。。好吧暂且把它看做是python对一个对象的表达形式吧,就如同java中对象打印一样,获得是对应的hashcode值。    

      next()读取生成器中的数据的系统方法。该方法获取生成器中的数据遇到yield则执行数据返回。yield的功能等同于return,不同点在于yield挂机程序执行,并不会结束方法执行。

      这里对于方法next()使用不是绝对安全的,在地十二行处调用next()方法抛出了一个StopIteration异常,意思就是已经是最后一个数据了,没有更多数据了。那么怎么避免这个问题那???也许有些人想到了for循环,那么对于这个generator是否也适用???我们有我们的办法,isinstance()。想到了就去做。

    1 >>> isinstance(oGenerator, Iterable)
    2 True
    3 >>>

      如上代码证明了Generator生成器其实也是Iterable的子类,那么这就简单了。

    >>> oGenerator = (n for n in range(1, 5))
    >>> for item in oGenerator:
    ...     print(item)
    ...
    1
    2
    3
    4
    >>>

      到了这里我们也就发现了正确的读取生成器Generator中数据的方法。

      下一步就是如何自定义生成器????

     1 >>> def step():
     2 ...  print('step 1')
     3 ...  yield 1
     4 ...  print('step 2')
     5 ...  yield 6
     6 ...  print('step 3')
     7 ...  yield 12
     8 ...
     9 >>>
    10 >>> g = step()
    11 >>> g
    12 <generator object step at 0x00000000024D2EB8>
    13 >>> next(g)
    14 step 1
    15 1
    16 >>> next(g)
    17 step 2
    18 6
    19 >>> next(g)
    20 step 3
    21 12
    22 >>>

      自定义Generator适用关键字yield,方法在执行next()过程中,每当遇到yield都会直接返回,但是方法并未真正结束,仅仅是暂停。当你再一次调用next()则会在当前暂停出继续执行,知道执行完全结束,最后抛出StopIteration异常。

      这里演示过程中采用了next()方法遍历自定义的Generator,在真正使用过程中尽量使用for循环,因为for内部会处理StopIteration异常。

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 矩阵加法
    Java实现 蓝桥杯VIP 算法训练 一元三次方程
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 平方计算
    Java实现 蓝桥杯VIP 算法训练 乘法表
    Java实现 蓝桥杯VIP 算法训练 乘法表
    监管只是压倒网盘业务的一根稻草,但不是主要原因(答案只有一个:成本!)
  • 原文地址:https://www.cnblogs.com/liemng/p/7744551.html
Copyright © 2011-2022 走看看