Python(3)高级特性

一、切片

  • python的使用中,对于列表、元组的元素取值是非常常见的,例如:
  • *注意:切片是顾头不顾尾的
>>> L = ["aaa","bbb","ccc","ddd"]
>>> print(L)
['aaa', 'bbb', 'ccc', 'ddd']

>>> print(L[0],L[1],L[2])
aaa bbb ccc

>>> for i in range(3):
...     a.append(L[i])
...

>>> print(a)
['aaa', 'bbb', 'ccc']

>>> print(L[0:3])
['aaa', 'bbb', 'ccc']
>>> print(L[:3])
['aaa', 'bbb', 'ccc']

>>> L = list(range(100))
>>> print(L)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> print(L[:])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> print(L[:10])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(L[10:20])
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> print(L[:-1])
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98]
>>> print(L[-10:-1])
[90, 91, 92, 93, 94, 95, 96, 97, 98]
>>> print(L[-20:-10])
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]
>>> print(L[-10:])
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

>>> print(L[::5])
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
  • 上面的是列表的取值案例,列表的切片最终输出的结果还是列表
  • python的切片还可以引用在其他数据类型上,如元组、字符串等,例如:

>>> T = (1,2,3,4,5)
>>> print(T)
(1, 2, 3, 4, 5)
>>> print(T[1:3])
(2, 3)
>>> print(T[-3:])
(3, 4, 5)

>>> S = "ABCDEFG"
>>> print(S)
ABCDEFG
>>> print(S[4:])
EFG
>>> print(S[::3])
ADG
  • 在自己实践过之后可以发现,元组切片后的输出还是元组,同样字符串切片后还是字符串
  • 这里引用一个小案例,不使用strip函数,利用切片来去除首位的空格:

def trim(s):
    if s[:1] != ' ' and s[-1:] != ' ':
        return s
    elif s[:1] == ' ':
        return trim(s[1:])
    else:
        return trim(s[:-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('测试成功!')

这段代码通过切片去判断首位是否有空格,有的话会再次调用函数,并且引用第1元素或第-1元素来去除空格,然后继续做判断,直至首尾没有空格

二、迭代

  • 首先要知道的是,通过for循环来遍历列表、元组、字符串等,这种遍历就称为迭代
  • 需要注意的是,python中的迭代是直接通过 for in的这种方式来完成的,而其他语言,比如C语言中的迭代是通过下标完成的,即 i++这种方式。并且python的for循环还可以使用在其他的可迭代的数据类型上
  • 除了列表、元组这种有下标的数据类型,python中的for循环还可以使用在其他没有下标的可迭代数据类型上,如字典:
>>> L = {"aaa":1,"bbb":2,"ccc":3}
{'aaa': 1, 'bbb': 2, 'ccc': 3}
>>> for i in L:
...     print(i)
...

aaa
bbb
ccc

>>> for i in L.values():
...     print(i)
...

1
2
3

>>> for x,y in L.items():
...     print(x,y)
...

aaa 1
bbb 2
ccc 3

要注意的是,因为字典的存储不是按照列表的方式顺序排列的,所以迭代出的结果有可能会不同

  • 其他类型的一些循环:

>>> S = "ABCDEFG"
>>> print(S)
ABCDEFG
>>> for i in S:
...     print(i)
...

A
B
C
D
E
F
G

>>> T = (1,2,3,4)
>>> for i in T:
...     print(i)
...

1
2
3
4

>>> L = [1,2,3,4]
>>> for i in L:
...     print(i)
...

1
2
3
4
  • 在上面的案例中,可以看出,for循环只要是使用于可迭代的数据类型,都可以正常运行,那怎么看是否是可迭代的数据类型呢,python提供了相应的方法:
>>> from collections.abc import Iterable
>>> isinstance('aaaa',Iterable)
True
>>> isinstance([1,2,3],Iterable)
True
>>> isinstance((1,2,3),Iterable)
True
>>> isinstance(S,Iterable)
True
>>> isinstance(L,Iterable)
True
>>> isinstance(T,Iterable)
True
>>> isinstance({"aaa":1,"bbb":2},Iterable)
True
  • 引用其他的一些小案例:
>>> L = [1,2,3,4,5]
>>> for x,y in enumerate(L):
...     print(x,y)
...

0 1
1 2
2 3
3 4
4 5

>>> L = [(1,2),(3,4),(5,6)]
>>> for x,y in L:
...     print(x,y)
...

1 2
3 4
5 6

def findMinAndMax(L):
    if L == []:
        return (None,None)
    else:
        min=L[0]
        max=L[0]
        for i in L:
            if i > max:
                max = i
            if i < min:
                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('测试成功!')

先创建一个参照数,然后循环列表依次对比参照数,从而取出最大值和最小值

三、列表推导式

  • 列表推导式,也叫列表生成式,(List Comprehensions),是python内置的一个简单、强大的可以用来创建列表的生成式
  • 下面举一些简单的例子进行对比:

>>> L = list(range(1,11))
>>> print(L)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> N = []
>>> for i in L:
...     N.append(i*i)
...

>>> print(N)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

>>> [i * i for i in L]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

[i * i for i in L]
在我的理解中,其实就是直接操作列表的值,使用for循环去指定要操作的列表,把里面的值拿出来,然后直接在开头对值进行操作,从而达到想要的效果

>>> L = ["Aaa","Bbb","Ccc"]
>>> [i.lower() for i in L]
['aaa', 'bbb', 'ccc']
使用lower函数把字符变成小写

&#x6CE8;&#x610F;&#xFF1A;&#x5217;&#x8868;&#x63A8;&#x5BFC;&#x5F0F;&#x662F;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x65B0;&#x5217;&#x8868;&#xFF0C;&#x4E0D;&#x4F1A;&#x4FEE;&#x6539;&#x539F;&#x5217;&#x8868;&#x7684;&#x5143;&#x7D20;

  • 在熟悉基本的列表推导式后,我们还可以使用if语句、多层for循环来创建列表推导式,例如:

>>> L = list(range(11))
>>> print(L)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [i for i in L if i % 2 == 0]
[0, 2, 4, 6, 8, 10]
可以发现if语句是写在末尾的,如果想要加else呢?就需要换一下位置了
>>> [i if i % 2 == 0 else -i for i in L]
[0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
这个推导式的意思是除以二余零的直接输出,否则变成负数输出

>>> [x + y for x in "abc" for y in "efg" ]
['ae', 'af', 'ag', 'be', 'bf', 'bg', 'ce', 'cf', 'cg']

>>> [x + y + i for x in "abc" for y in "efg" for i in "hij"]
['aeh', 'aei', 'aej', 'afh', 'afi', 'afj', 'agh', 'agi', 'agj', 'beh', 'bei', 'bej', 'bfh', 'bfi', 'bfj', 'bgh', 'bgi', 'bgj', 'ceh', 'cei', 'cej', 'cfh', 'cfi', 'cfj', 'cgh', 'cgi', 'cgj']
但是一般只会用到两层循环,两层以上的就很少用了

&#x6CE8;&#x610F;&#xFF1A;&#x5728;&#x5217;&#x8868;&#x63A8;&#x5BFC;&#x5F0F;&#x4E2D;&#xFF0C;for&#x540E;&#x9762;&#x8DDF;&#x7684;if&#x662F;&#x8FC7;&#x6EE4;&#x6761;&#x4EF6;&#xFF0C;&#x4E0D;&#x80FD;&#x8DDF;else&#x5426;&#x5219;&#x4F1A;&#x62A5;&#x9519;&#xFF0C;&#x800C;if..else&#x662F;&#x8868;&#x8FBE;&#x5F0F;&#xFF0C;&#x6240;&#x4EE5;&#x9700;&#x8981;&#x5199;&#x5728;&#x524D;&#x9762;

  • 之前说过for循环只要是可迭代的数据类型都可以使用,那么同样的列表推导式也可以进行引用

>>> d = {"a":1,"b":2,"c":3}
>>> [x + '=' + y for x,y in d.items()]
Traceback (most recent call last):
  File "", line 1, in <module>
  File "", line 1, in <listcomp>
TypeError: can only concatenate str (not "int") to str
在引用字典时,发现报错了,原来是因为int类型导致的报错
>>> d = {"a":"1","b":"2","c":"3"}
>>> [x + '=' + y for x,y in d.items()]
['a=1', 'b=2', 'c=3']

&#x6CE8;&#x610F;&#xFF1A;&#x5728;&#x4F7F;&#x7528;&#x5217;&#x8868;&#x63A8;&#x5BFC;&#x5F0F;&#x65F6;&#xFF0C;&#x8981;&#x6CE8;&#x610F;&#x5217;&#x8868;&#x3001;&#x5143;&#x7EC4;&#x3001;&#x5B57;&#x5178;&#x5143;&#x7D20;&#x7684;&#x6570;&#x636E;&#x7C7B;&#x578B;&#xFF0C;&#x6BD4;&#x5982;&#x8981;&#x4F7F;&#x7528;lower&#x51FD;&#x6570;&#x8F6C;&#x6362;&#x5927;&#x5C0F;&#x5199;&#x65F6;&#xFF0C;&#x5982;&#x679C;&#x5217;&#x8868;&#x4E2D;&#x5143;&#x7D20;&#x6709;int&#x7C7B;&#x578B;&#x7684;&#xFF0C;&#x90A3;&#x4E48;&#x5C31;&#x4F1A;&#x62A5;&#x9519;&#xFF0C;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5185;&#x5EFA;&#x51FD;&#x6570;isinstance&#x6765;&#x5224;&#x65AD;&#x4E00;&#x4E2A;&#x53D8;&#x91CF;&#x662F;&#x4E0D;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x4F8B;&#x5982;&#xFF1A;

>>> L = ["Aaa","Bbb",111,222,"Ccc",None]
>>> [ i.lower() for i in L]
Traceback (most recent call last):
  File "", line 1, in <module>
  File "", line 1, in <listcomp>
AttributeError: 'int' object has no attribute 'lower'
这样会报错,所以可以加一个isinstance的过滤条件
>>> [ i.lower() for i in L if isinstance(i,str) == True]
['aaa', 'bbb', 'ccc']

三、生成器(generator)

  • 通过上面的列表推导式,我们可以直接创建一个列表,但是列表的容量肯定是有限的,如果要创建一个100万个元素的列表,不仅会占用很大的存储空间,而且,如果说里面的元素有百分之90都用不到的话,那么就会浪费很大的空间,而生成器就可以解决这个问题
  • 生成器可以根据某个算法在循环过程中不断的推算后续的元素,这样就不用创建完整的列表,从而节省大量的空间,而这种一边循环一边生成的机制,就叫生成器==(generator)==
  • 下面是创建生成器的案例:

>>> L = list(range(11))
>>> [ i * i for i in L]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> ( i * i for i in L)
<generator object <genexpr> at 0x0000022979D4C0B0>
可以发现生成器不会直接输出结果

>>> g = ( i * i for i in L)
>>> g
<generator object <genexpr> at 0x0000022979D4DA80>
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
100
>>> next(g)
Traceback (most recent call last):
  File "", line 1, in <module>
StopIteration

>>> g = ( i * i for i in L)
>>> for x in g:
...     print(x)
...

0
1
4
9
16
25
36
49
64
81
100
  • 从上面的例子可以看出,生成器是可以直接使用for循环调用的,所以说在实际使用生成器时,几乎不会使用next去依次调用
  • 下面引用一个案例,实现斐波拉契数列

def fbl(n):
    x,y,i = 0,0,1
    while x < n:
        print(i)
        y,i = i,y + i
        x = x + 1
    return 'done'

fbl(6)

1
1
2
3
5
8

定义x为循环的次数,每次循环会加一,当x等于函数传入的参数n时,while循环就会结束
而y和i在每次循环时,y会赋予i的值,而i会赋予y+i的值,这样实现的效果就是:
1:y=1,x=0+1=1
2:y=1,x=1+1=2
3:y=2,x=1+2=3
4:y=3,x=2+3=5
5:y=5,x=3+5=8
更好理解的就是x2=y1+x1,x3=y2+x2,x4=y3+y3这种规律
  • 从上面的案例中可以看出,斐波拉契数列就是根据上一个运算结果推算出下一个运算结果,这就比较像生成器的特性了
  • 而上面定义的函数只需要把print(i)改为yield i就可以变成一个生成器:

def fbl(n):
    x,y,i = 0,0,1
    while x < n:
        yield i
        y,i = i,y + i
        x = x + 1
    return 'done'

f = fbl(6)
print(f)
for a in f:
    print(a)

<generator object fbl at 0x000001F1B9BED8C0>
1
1
2
3
5
8

这里的函数和上面的普通函数只改变了一个关键字,但是因为这个关键字,使函数执行的流程发生了改变,上面的普通函数就是依次的顺序执行,遇到return语句或是到了最后一行语句就会返回,而这里的函数变成了只有在遇到next函数或for循环时才会在yield关键字的语句位置进行返回,再次使用next或继续for循环时,会从上次yield语句的位置继续执行,直到再次遇到yield语句然后再次进行返回,这里的函数其实就变成了生成器函数

def test():
    print('aaa')
    yield
    print('bbb')
    yield
    print('ccc')
    yield

a = test()
next(a)
print("1")
next(a)
print("2")
next(a)
print("3")
next(a)

aaa
1
bbb
2
ccc
3
Traceback (most recent call last):
  File "c:\Users\12488\Desktop\python\pachong.py", line 17, in <module>
    next(a)
StopIteration
这里其实就更直观了,在第一次调用时,在第一个yield停下了,从而输出了aaa,第二次从第一个yield位置继续执行在第二个yield的位置停下,从而输出的bbb,第三次从第二个yield的位置继续执行,在第三个的yield位置停下,从而输出了ccc,第四次的时候,因为已经没有yield关键字了,所以就报错了

注意:

1、如果一个函数中包含yield关键字,那么这个函数就会变成生成器函数,而调用一个生成器函数将会返回一个生成器的数据
2、调用生成器函数会创建一个生成器对象,多次调用生成器函数会创建多个相互独立的生成器,示例:


def test():
    print('aaa')
    yield
    print('bbb')
    yield
    print('ccc')
    yield

next(test())
print("1")
next(test())
print("2")
next(test())
print("3")
next(test())

aaa
1
aaa
2
aaa
3
aaa
可以发现每次都是只到第一个yield就停下了,这就是因为只调用了生成器函数,所以每次都是创建新的生成器,而上一个脚本是把生成器函数赋值了,每次调用的是相同的生成器,很明显上一个脚本的写法才是正确的
  • 这里引用廖雪峰大神的一个案例:
1、在使用for循环调用生成器时,会发现拿不到生成器return语句的返回值,如果想拿到返回值,必须捕获StopIteration的错误,返回值包含在StopIteration的value值中:

def fbl(n):
    x,y,i = 0,0,1
    while x < n:
        yield i
        y,i = i,y + i
        x = x + 1
    return 'done'

f = fbl(6)
while True:
    try:
        x = next(f)
        print('f:',x)
    except StopIteration as e:
        print('return value:',e.value)
        break

f: 1
f: 1
f: 2
f: 3
f: 5
f: 8
return value: done

2、实现杨辉三角

def triangles():
    L = [1]
    while True:
        yield L
        X = [0] + L
        Y = L + [0]
        L = [X[i] + Y[i] for i in range(len(X))]

n = 0
results = []
for t in triangles():
    results.append(t)
    n = n + 1
    if n == 10:
        break

for t in results:
    print(t)

if results == [
    [1],
    [1, 1],
    [1, 2, 1],
    [1, 3, 3, 1],
    [1, 4, 6, 4, 1],
    [1, 5, 10, 10, 5, 1],
    [1, 6, 15, 20, 15, 6, 1],
    [1, 7, 21, 35, 35, 21, 7, 1],
    [1, 8, 28, 56, 70, 56, 28, 8, 1],
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
]:
    print('测试通过!')
else:
    print('测试失败!')

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
测试通过!

def triangles():
    L = [1]
    while True:
        yield L
        x = [0] + L
        y = L + [0]
        L = [x[i] + y[i] for i in range(len(x))]

下面就是每一次循环时的规律,可以看出来每次都是相加、重组的一个流程
L = [1]
x=[0,1],y=[1,0]
range(len(x)) = range(2)
x[0] + y[0] = 0 + 1 = 1
x[1] + y[1] = 1 + 0 = 1
[1,1]

L = [1,1]
x=[0] + [1,1] = [0,1,1]
y=[1,1] + [0] = [1,1,0]
range(len(x)) = range(3)
x[0] + y[0] = 0 + 1 = 1
x[1] + y[1] = 1 + 1 = 2
x[2] + y[2] = 1 + 0 = 1
[1,2,1]

L = [1,2,1]
x=[0] + [1,2,1] = [0,1,2,1]
y=[1,2,1] + [0] = [1,2,1,0]
range(len(x)) = range(4)
x[0] + y[0] = 0 + 1 = 1
x[1] + y[1] = 1 + 2 = 3
x[2] + y[2] = 2 + 1 = 3
x[3] + y[3] = 1 + 0 = 1
[1,3,3,1]

L = [1,3,3,1]
x=[0] + [1,3,3,1] = [0,1,3,3,1]
y=[1,3,3,1] + [0] = [1,3,3,1,0]
range(len(x)) = range(5)
x[0] + y[0] = 0 + 1 = 1
x[1] + y[1] = 1 + 3 = 4
x[2] + y[2] = 3 + 3 = 6
x[3] + y[3] = 3 + 1 = 4
x[4] + y[4] = 1 + 0 = 1
[1,4,6,4,1]

&#x6CE8;&#x610F;&#xFF1A;&#x751F;&#x6210;&#x5668;&#x51FD;&#x6570;&#x7684;&#x8C03;&#x7528;&#x4F1A;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x751F;&#x6210;&#x5668;&#x5BF9;&#x8C61;&#xFF0C;&#x800C;&#x666E;&#x901A;&#x51FD;&#x6570;&#x4F1A;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x8C03;&#x7528;&#x7ED3;&#x679C;

四、迭代器

  • 经过上面的学习,可以知道可以直接进行for循环的数据类型有:列表(list),元组(tuple)、字典(dict)、集合(set)、字符串(str)等,这些都是集合数据类型的,还有一个种是生成器(generator),包括了生成器和生成器函数 &#xFF08;&#x5E26;yield&#x5173;&#x952E;&#x5B57;&#x7684;&#x51FD;&#x6570;&#xFF09;
  • for循环可以作用于上述所说的所有数据类型,而这些数据类型又称为 &#x53EF;&#x8FED;&#x4EE3;&#x6570;&#x636E;&#x7C7B;&#x578B;(Iterable),利用 isinstance()函数可以判断一个数据是否为可迭代的数据类型
>>> from collections.abc import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('aaa', Iterable)
True
>>> isinstance((i for i in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

  • 我们知道生成器不但可以使用for循环,还可以使用 next()函数不断调用直到抛出 StopIteration错误,而这种可以被 next()函数调用并不断返回下一个值的数据类型,也叫做 &#x8FED;&#x4EE3;&#x5668;(Iterator),同样的使用 isinstance()函数可以判断是否为迭代器:
>>> from collections.abc import Iterator
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('aaa', Iterator)
False
>>> isinstance((i for i in range(10)), Iterator)
True

&#x6CE8;&#x610F;&#xFF1A;&#x751F;&#x6210;&#x5668;&#x4E3A;Iterable&#x800C;&#x8FED;&#x4EE3;&#x5668;&#x4E3A;Iterator

  • 经过上面的案例,可以看出生成器既是可迭代数据类型,也是迭代器数据类型,但是为什么其他的可迭代数据不是迭代器数据类型呢?如列表、字典、字符串等

    这是因为python中的迭代器表示的是一个数据流,这个数据流是可以被 next()函数不断调用并返回下一个值,直到没有数据时报 StopIteration错误。 这也说明了迭代器的计算是惰性的,只有在需要返回下一个数据时才会进行计算,而列表、字典、字符串这些数据在创建的时候,里面的元素就已经定义好了,在需要返回时并不会计算,而是直接返回。 他们的区别还在于迭代器可以表示一个无限大的数据流,例如所有自然数,因为他的计算模式是惰性的,而像列表、字典、字符串这种的,很明显存储的元素是有限的,所以它们不是迭代器的数据类型

  • 列表、字典、字符串等虽然不是迭代器的数据类型,但是可以通过函数 iter()来获取一个迭代器的数据,例如:
>>> from collections.abc import Iterator
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter({}), Iterator)
True
>>> isinstance(iter('aaa'), Iterator)
True
  • 最后引入几个知识点:

1、python的for循环本质就是通过不断调用 next()函数实现的
2、凡是for循环可以调用的类型都是可迭代数据类型
3、凡是可以使用 next()函数不断调用输出结果的数据都是迭代器数据类型
以看出生成器既是可迭代数据类型,也是迭代器数据类型,但是为什么其他的可迭代数据不是迭代器数据类型呢?如列表、字典、字符串等

这是因为python中的迭代器表示的是一个数据流,这个数据流是可以被 next()函数不断调用并返回下一个值,直到没有数据时报 StopIteration错误。
这也说明了迭代器的计算是惰性的,只有在需要返回下一个数据时才会进行计算,而列表、字典、字符串这些数据在创建的时候,里面的元素就已经定义好了,在需要返回时并不会计算,而是直接返回。
他们的区别还在于迭代器可以表示一个无限大的数据流,例如所有自然数,因为他的计算模式是惰性的,而像列表、字典、字符串这种的,很明显存储的元素是有限的,所以它们不是迭代器的数据类型

  • 列表、字典、字符串等虽然不是迭代器的数据类型,但是可以通过函数 iter()来获取一个迭代器的数据,例如:
>>> from collections.abc import Iterator
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter({}), Iterator)
True
>>> isinstance(iter('aaa'), Iterator)
True
  • 最后引入几个知识点:

1、python的for循环本质就是通过不断调用 next()函数实现的
2、凡是for循环可以调用的类型都是可迭代数据类型
3、凡是可以使用 next()函数不断调用输出结果的数据都是迭代器数据类型

Original: https://blog.csdn.net/rzy1248873545/article/details/124535761
Author: 礁之
Title: Python(3)高级特性

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/748877/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 研发工程师-编程题(python)

    1、丑数 题目描述:给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。 丑数 就是只包含质因数 2、3 和/或 5 的正整数。(…

    Python 2023年8月1日
    068
  • 【Python】利用matplotlib在Pycharm中显示本地图片

    前言 近来在做绘图的工作,结果是会导出一张 png图片,但苦于每次都要点击图片才能查看。为解决这一痛点,遂有此文 图片显示 鄙人有一图,名为 &#x56E0;&#x…

    Python 2023年8月30日
    069
  • 利用Scrapy框架爬取汽车之家图片(详细)

    爬取结果 爬取步骤 创建爬虫文件 进入cmd命令模式下,进入想要存取爬虫代码的文件,我这里是进入e盘下的E:\pystudy\scraping文件夹内 C:\Users\wei&g…

    Python 2023年10月3日
    038
  • pyechart数据可视化丨制作桑基图(sankey)的最简单方法

    前言最近在分析超期库存数据, 每天4万条左右, 数据的特点是有很多 分类变量, 为了展现这些变量的关系, 想到了桑吉图。 Pyechart官网上有关于桑基图的案例, 但是如何用日常…

    Python 2023年8月17日
    068
  • 简单对比多线程与多进程-python(探索ing)

    我又来了,哈哈。电脑配置:cpu为i5-10300H运行内存为16G 测试代码如下 def add(): lock.acquire() with open(‘test.txt’, …

    Python 2023年6月9日
    083
  • 女友晚安之后依然在线:python男友用20行代码写了个小工具

    大家好,我是Lex 喜欢欺负超人那个Lex擅长领域:python开发、网络安全渗透、Windows域控Exchange架构今日重点:python用20代码实现录屏功能代码干货满满,…

    Python 2023年7月31日
    045
  • Vue3 JS 与 SCSS 变量相互使用

    在开发中会遇到如下需求: JS 中使用 SCSS 变量。如在 scss 中定义了一个颜色, el-menu 组件使用该颜色作为背景色,此时需要获取 scss 变量,通过 backg…

    Python 2023年10月18日
    096
  • 美多商城之商品(2)

    美多商城之商品(2) 1.商品搜索 * 1.1.全文检索方案Elasticsearch 1.2.Haystack扩展建立索引 1.3.渲染商品搜索结果 2.商品详情页 * 2.1….

    Python 2023年8月5日
    045
  • python pandas dropna_Pandas之Dropna滤除缺失数据的实现方法

    约定: import pandas as pd import numpy as np from numpy import nan as NaN 滤除缺失数据 pandas的设计目标…

    Python 2023年8月22日
    074
  • Vue 和 Django 实现 Token 身份验证

    使用 Django 编写的 B/S 应用通常会使用 Cookie + Session 的方式来做身份验证,用户登录信息存储在后台数据库中,前端 Cookie 也会存储少量用于身份核…

    Python 2023年5月23日
    054
  • python飞机大战简单的实现

    制作初衷 这几天闲来没事干,就想起来好长时间没做过游戏了,于是就想做一个游戏练练手,为了起到一个练习的目的就使用了自己不是太熟练的python这门语言来编写,代码都有备注,大家可以…

    Python 2023年9月18日
    071
  • Audio基本概念及处理流程

    1、声音的三要素:频率、振幅、波形 1.1、频率: 声波的频率,即声音的音调, 音调越高,频率越大;音调越低,频率越小。 人类听觉的频率(音调)范围为 20Hz–20K…

    Python 2023年11月6日
    039
  • Pygame Event事件模块(详细示例)

    Pygame Event事件模块(详细示例) 事件(Event)是 Pygame 的重要模块之一,它是构建整个游戏程序的核心,比如鼠标点击、键盘敲击、游戏窗口移动、调整窗口大小、触…

    Python 2023年9月19日
    043
  • 第二证券|锂离子聚合物电池的分类和使用注意事项

    根据锂离子电池所用电解质资料的不同,锂离子电池分为液态锂离子电池和聚合物锂离子电池。聚合物锂离子电池所用的正负极资料与液态锂离子都是相同的,正极资料分为钴酸锂、锰酸锂、三元资料和磷…

    Python 2023年10月27日
    036
  • Python学习笔记(八)–Django框架

    1.什么是框架? 车架是节目的骨架,主体结构也是半成品。 [En] The frame is the skeleton of the program, and the main s…

    Python 2023年5月24日
    068
  • matplotlib–pyplot

    前言 上一节我们提到, matplotlib绘图有两种风格 显式创建图形与轴空间,并在其上调用方法的OO风格 依靠 pyplot自动创建和管理图形和轴,并使用 pyplot函数进行…

    Python 2023年8月31日
    052
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球