Python学习笔记四

参考教程:廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

Python高级特性

一、切片

如果要取出一个列表或元组的部分元素,可以通过直接下标方法:

lista=['apple','banana','cherry']
lista[0]
lista[1]
lista[2]

但如果要取再多个,或者前面(后面)多少个,或中间多少个,直接访问的方法就很不方便了。

Python提供了切片(Slice)操作符来实现这种功能,通过[m:n]的方式提取从第m个(含)到第n个(不含)范围内元素。

numbers=list(range(20))

#提取前面5个元素
print(numbers[:5])

#提取最后3个元素
print(numbers[-3:])

#提取从第3个元素开始的5个元素
print(numbers[2:7])

#还可以设置间隔幅度
#提取奇数,通过第二个冒号后设置幅度
print(numbers[1::2])

#直接复制原列表
lista=numbers[:]
print(lista)

这种操作对于字符串和元组一样有效:

print('123 abc XYZ 890'[3:10])

练习题:

#利用切片操作,实现去掉字符串首尾空格的功能
def trim(s):
    l=len(s)
    #如果是空字符串
    if l==0:
        return ''
    else:
        counter=0
        for x in s:
            if x==' ':
                counter+=1
            else:
                break
        #字符串全是空格的情况
        if counter==l:
            return ''
        else:           
            m=0
            n=-1
            for a in s:
                if a==' ':
                    m+=1
                else:
                    break
            while s[n]==' ':
                n=n-1

            return s[m:(l+n+1)]

# 测试:
if trim('hello  ') != 'hello':
    print('测试失败!')
elif trim('  hello') != 'hello':
    print('测试失败!')
elif trim('  hello  ') != 'hello':
    print('测试失败!')
elif trim('  hello  world  ') != 'hello  world':
    print('测试失败!')
elif trim('') != '':
    print('测试失败!')
elif trim('    ') != '':
    print('测试失败!')
else:
    print('测试成功!')

 二、迭代

如果给定一个可迭代对象,Python中可通过for...in来进行遍历循环,如字符串、列表、元组、字典这些都是可迭代对象。

#字符串迭代
for ch in 'ABC':
    print ch
lista=list(range(1,101))
sum=0
#列表迭代
for i in lista:
    sum+=i
print('sum=',sum)
d = {'a': 1, 'b': 2, 'c': 3}
#字典的键迭代
for key in d:
    print (key)
#字典的值迭代:
for value in d.values():
    print (value)
#键值同时迭代
for k,v in d.items()
    print(k,':',v)

Python中提供了collections模块中的iterable类型判断:

>>> from collections import Iterable
>>> isinstance('abc',Iterable)
True
>>> isinstance([1,10,100],Iterable)
True
>>> isinstance(False,Iterable)
False
>>> isinstance(18,Iterable)
False

Python中提供了enumerate函数,可以把一个列表变成索引-元素对,这样就可以在迭代索引和元素本身:

>>> for i,value in enumerate(['x','y','z']):
    print (i,value)

    
0 x
1 y
2 z

迭代两个变量的情况:

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print(x, y)
...
1 1
2 4
3 9

练习:

# -*- coding: utf-8 -*-

#请使用迭代查找一个list中最小和最大值,并返回一个tuple:
def findMinAndMax(L):
    if not L:
        return (None,None)
    else:
        max=L[0]
        min=L[0]
        for i in L:
            if max<i:
                max=i
            if min>i:
                min=i
        return (min,max)


# 测试
if findMinAndMax([]) != (None, None):
    print('测试失败!')
elif findMinAndMax([7]) != (7, 7):
    print('测试失败!')
elif findMinAndMax([7, 1]) != (1, 7):
    print('测试失败!')
elif findMinAndMax([7, 1, 3, 9, 5]) != (1, 9):
    print('测试失败!')
else:
    print('测试成功!')

 三、列表生成式

列表生成式是Python中内置可以用来生成列表的方法。

#生成0~49的整数列表
list(x for x in range(0,50))
#同上更简单的写法
list(range(0,50))
#奇偶数的列表生成
list(x for x in range(0,20) if x%2==0)
list(x for x in range(0,20) if x%2==1)
#生成1~9对应整数的平方值列表
list(x*x for x in range(1,10))
#两个变量两次迭代生成乘法算式
list(str(x)+'*'+str(y)+'='+str(x*y) for x in range(1,10) for y in range(1,10))
#迭代字典的列表生成
d={'A':'100,'B':200,'C':300}
list(m+'='+str(n) for m,n in d.items())
#判断一个列表中元素是否为字符串
#重新生成只包含其中字符串的列表,并且转为小写
# -*- coding: utf-8 -*-
L1 = ['Hello', 'World', 18, 'Apple', None]
L2 = [x for x in L1 if isinstance(x,str)]
print(L2)
if L2 == ['hello','world','apple']:
    print('测试通过!')
else:
    print('测试失败!')

 四、生成器

受内存限制,列表的容量总是有限的;同时某些情况下,一个包含大量元素的列表我们只需要访问前面若干个元素,这样的话列表的其他元素就浪费了大量内存资源。Python中提供了一种在循环的过程中不断推算后续元素的方法,这样就不必创建完整的列表,这种方式称为生成器(generator)。

举例说明上述说法,比如需要生成一个2,4,8,16,32...,2^n的序列,这显然是一个无穷的序列,需要输出多少个元素完全依靠用户的需求。

>>> def fun2N():
    n=1
    while True:
        yield 2**n
        n=n+1

        
>>> x=fun2N()
>>> next(x)
2
>>> next(x)
4
>>> next(x)
8
>>> next(x)
16
>>> next(x)
32
>>> next(x)
64
>>> next(x)
128

生成器有两种创建的方法:

第一种类似于列表生成式,只是把[]改成():

#生成列表L
L=[x*x for x in range(10)]
#创建类似的生成器gL
gL=(x*x for x in range(10))

如上述创建好生成器后,可以通过next()方法逐个获得生成器的返回值

#这里看出创建的gL是一个生成器对象
>>> gL
<generator object <genexpr> at 0x0000000002BFA518>
#通过next()逐个获取返回值
>>> next(gL)
0
>>> next(gL)
1
>>> next(gL)
4
>>> next(gL)
9
>>> next(gL)
16
>>> next(gL)
25
>>> next(gL)
36
>>> next(gL)
49
>>> next(gL)
64
>>> next(gL)
81
#循环结束,抛出StopIteration错误
>>> next(gL)
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    next(gL)
StopIteration

但上面的next()方法明显太麻烦了,因为generator也是可迭代对象,所以可以通过for/in循环去访问元素。先测试一下可迭代性:

>>> from collections import Iterable
>>> isinstance(gL,Iterable)
True
>>> gL=(x*x for x in range(5))
>>> for i in gL:
    print (i)

    
0
1
4
9
16

创建生成器的第二种方法是函数的方式,比如对应上述生成器的函数生成方法如下:

def gL():
    for i in range(5):
        yield i**2

与函数的定义不同,生成器的函数创建方式中返回是通过yield关键字来实现;在执行过程中不断执行、中断、执行、中断直至没有元素了结束(抛出StopIteration)。每一次生成的就是yield语句的返回值,下一次生成再从上一次yield的下一句开始执行直至本次yield返回为止。

生成器的函数创建方法中也可以包括return语句,比如在上述gL中,我们可以在所有元素生成结束后给它一个return的返回值:

def gL():
    for i in range(5):
        yield i**2
    return 'DONE'

斐波拉契数列是一个无限的集合,无法用列表保存,但却可以通过生成器的方式表示:

def fibGen():
    a,b=1,1
    while True:
        yield a
        a,b=b,a+b
        
x=input("输入1结束输出,其他继续输出斐波拉契数列:")
f1=fibGen()
while (x!=str(1)):
    print(next(f1))
    x=input()
    

因为生成器的可迭代性,所以在给定的条件下,我们可以利用for/in循环方式输出一定条件下的斐波拉契数列:

#输出小于2000的数列值
for i in fibGen():
    if (i<2000):
        print (i)
    else:
        break

上面的方法也可以给出参数:

def fibGen1(n):
    a,b=1,1
    counter=0
    while (counter<n+1):
        yield a
        a,b=b,a+b
        counter=counter+1

for x in fibGen1(16):
    print(x)

练习:

'''
杨辉三角定义如下:

          1
         / \
        1   1
       / \ / \
      1   2   1
     / \ / \ / \
    1   3   3   1
   / \ / \ / \ / \
  1   4   6   4   1
 / \ / \ / \ / \ / \
1   5   10  10  5   1
把每一行看做一个list,试写一个generator,不断输出下一行的list:
'''
#思路:把上一个列表的最后补0后,当前列表的每个元素都可以通过上列表的俩元素之和得出
def yhsj():
    L=[1]
    while True:
        yield L
        L.append(0)
        L=[L[i]+L[i-1] for i in range(len(L))]
for xL in yhsj():
    print(xL)
    x=input("输入1停止输出")
    if (x==str(1)):
        break

五、迭代器

前面说到可以通过for循环的数据类型包括两类,一类是集合类如list,tuple,dict,set,str等;另外一类就是生成器generator;这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。可以使用isinstance()方法进行判断:

>>> isinstance('abc',Iterable)
True
>>> isinstance([x for x in range(9)],Iterable)
True
>>> isinstance((x for x in range(9)),Iterable)
True
>>> isinstance([],Iterable)
True
>>> isinstance({},Iterable)
True

而生成器除了可以同for循环来调用外还可以通过next()函数不断调用,直到结束,对于这种可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。一样可以通过isinstance()来判断:

>>> from collections import Iterator
>>> isinstance('ABC',Iterator)
False
>>> isinstance([],Iterator)
False
>>> isinstance({},Iterator)
False
>>> isinstance((x for x in range(9)),Iterator)
True
>>> isinstance([x for x in range(9)],Iterator)
False

可以看出list\dict\str都不是迭代器,可以通过iter()函数将他们转换成迭代器:

>>> isinstance(iter('ABC'),Iterator)
True
>>> isinstance(iter([1,2,3]),Iterator)
True

Python的Iterator对象表示的是一个数据流,可以被next()函数不断调用直到抛出StopIteration错误。我们不能提前知道这个输出序列的长度,只有需要返回下一个数据时候才会被计算出来。

 

posted @ 2018-03-03 11:12  tsembrace  阅读(229)  评论(0编辑  收藏  举报