当语句以冒号
:
结尾时,缩进的语句视为代码块。
缩进有利有弊。好处是强迫你写出格式化的代码,但没有规定缩进是几个空格还是Tab。按照约定俗成的管理,应该始终坚持使用
4个空格
的缩进。
Python程序是
大小写敏感
的,如果写错了大小写,程序会报错。
数据类型
计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种:
数据类型
数字(整形,长整形,浮点型,复数)
字符串
列表
元组
字典
整数
Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:
1
,
100
,
-8080
,
0
,等等。
计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用
0x
前缀和0-9,a-f表示,例如:
0xff00
,
0xa5b4c3d2
,等等。
浮点数
浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x10
9
和12.3x10
8
是完全相等的。浮点数可以用数学写法,如
1.23
,
3.14
,
-9.01
,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x10
9
就是
1.23e9
,或者
12.3e8
,0.000012可以写成
1.2e-5
,等等。
整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
字符串
字符串是以单引号
'
或双引号
"
括起来的任意文本,比如
'abc'
,
"xyz"
等等。请注意,
''
或
""
本身只是一种表示方式,不是字符串的一部分,因此,字符串
'abc'
只有
a
,
b
,
c
这3个字符。如果
'
本身也是一个字符,那就可以用
""
括起来,比如
"I'm OK"
包含的字符是
I
,
'
,
m
,空格,
O
,
K
这6个字符。
如果字符串内部既包含
'
又包含
"
怎么办?可以用转义字符
\
来标识,比如:
表示的字符串内容是:
转义字符
\
可以转义很多字符,比如
\n
表示换行,
\t
表示制表符,字符
\
本身也要转义,所以
\\
表示的字符就是
\
,可以在Python的交互式命令行用
print()
打印字符串看看:
print
(
'I\'m ok.'
)
效果如图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/b3fb0eaca51a4b8151b2aedaa2a41378.png)
print('I\'m learning\nPython.')
![](https://i-blog.csdnimg.cn/blog_migrate/5550a2e8293cea00c29f7df95e60b071.png)
print('\\\n\\')
![](https://i-blog.csdnimg.cn/blog_migrate/42456e997689088f9f0c48f18776be55.png)
print('\\\n\\')
![](https://i-blog.csdnimg.cn/blog_migrate/229638a81bad1e7e94f9dbe561c215ad.png)
如果字符串里面有很多字符都需要转义,就需要加很多
\
,为了简化,Python还允许用
r''
表示
''
内部的字符串默认不转义
print(
'\\\t\\'
)
![](https://i-blog.csdnimg.cn/blog_migrate/b1805591935c95cba8417c23f6ba6c73.png)
print(r'\\\t\\')
![](https://i-blog.csdnimg.cn/blog_migrate/421e1819a0097aa6748bed8b037986b3.png)
如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用'''...'''的格式表示多行内容
![](https://i-blog.csdnimg.cn/blog_migrate/851a7bd6dd78ebb14767d273122ff029.png)
注意在输入多行内容时,提示符由
>>>
变为
...
,提示你可以接着上一行输入,注意
...
是提示符,不是代码的一部分
当输入完结束符
```
和括号
)
后,执行该语句并打印结果。
如果写成程序并存为
.py
文件,就是:
print('''line1
line2
line3''')
![](https://i-blog.csdnimg.cn/blog_migrate/e1913c1c30e0614de9a9ee6b1cd3c61b.png)
布尔值
布尔值和布尔代数的表示完全一致,一个布尔值只有
True
、
False
两种值,要么是
True
,要么是
False
,在Python中,可以直接用
True
、
False
表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
![](https://i-blog.csdnimg.cn/blog_migrate/6539feab3b974a79f38f8808754f00b3.png)
布尔值可以用
and
、
or
和
not
运算。
and
运算是与运算,只有所有都为
True
,
and
运算结果才是
True
:
![](https://i-blog.csdnimg.cn/blog_migrate/559bd0b72fad4a559a84cacf5be5941b.png)
or运算是或运算,只要其中有一个为True,or运算结果就是True:
![](https://i-blog.csdnimg.cn/blog_migrate/dfaf24f6fea14288ac80e7340a525257.png)
not运算是非运算,它是一个单目运算符,把True变成False,False变成True:
![](https://i-blog.csdnimg.cn/blog_migrate/04f954a7880a63957913616feda6b9bc.png)
not运算是非运算,它是一个单目运算符,把True变成False,False变成True:
![](https://i-blog.csdnimg.cn/blog_migrate/82ef19e2ac2ea0ff49ec0763f99ebcb0.png)
布尔值经常用在条件判断中
空值
空值是Python里一个特殊的值,用
None
表示。
None
不能理解为
0
,因为
0
是有意义的,而
None
是一个特殊的空值。
变量
变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型。
变量在程序中就是用一个变量名表示了,变量名必须是大小写英文、数字和
_
的组合,且不能用数字开头,比如:
a =
1
变量
a
是一个整数。
t_007 =
'T007'
变量
t_007
是一个字符串。
Answer =
True
变量
Answer
是一个布尔值
True
。
在Python中,等号
=
是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:
a = 123 # a是整数
print(a)
a = 'ABC' # a变为字符串
print(a)
加单引号双引号的都是字符串
![](https://i-blog.csdnimg.cn/blog_migrate/a1cc559ee25bdd78dcb502d07e4e4c0e.png)
变量在内存中的存储形式:
在python中, 每一个变量在内存中创建,我们可以通过变量来查看内存中的值
![](https://i-blog.csdnimg.cn/blog_migrate/54d239f1908567cb6f74896fd3b076dd.png)
在python中通过指针改变变量的值
x = 1 说明x指向了内存中存储为1的地址,地址是1767137504
y = 2 说明y指向了内存
中存储为2的地址,地址是
1767137536
也就是说在执行x = 4,y = 5之后,x,y分别指向了不同的地址
![](https://i-blog.csdnimg.cn/blog_migrate/c351bee765d1da030c12493f11b85889.png)
当执行 x = y之后
x指向了y所指向的内存了,它们都指向同一块内存,
跟c里面的指针一样
![](https://i-blog.csdnimg.cn/blog_migrate/69f045c4d1b2979d38fa3ecebf0ff595.png)
linux 下
![](https://i-blog.csdnimg.cn/blog_migrate/d281262a14c8a57f6d32207e15de90dd.png)
(好像linux(64bit ubuntu)和windows(64bit windows10)占用的内存大小不一样)
在python中,一开始初始化存储在内存的东西是不可以改变的,我们所能改变的只是它的指向。
示意图为
![](https://i-blog.csdnimg.cn/blog_migrate/7e239a861cfc72ae1898619f9664858c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3a7247d5d3775d608f6540138ef29f11.png)
可以看出x和1的地址是一个地址,y的地址和2是一个地址。
所以
执行 x
= 1
,解释器创建了整数
和变量
x
,并把
x
指向
1所在的内存地址
:
执行x
= y
,解释器创建了变量
y
,并把
y
指向
x
指向a的内存地址
如果将x重新赋值abc x='abc',那么
解释器创建了字符串'abc',并把
x
的指向改为
'abc'所在的内存地址
,但
y
并没有更改
![](https://i-blog.csdnimg.cn/blog_migrate/934085717a0c121e70db16407eb32430.png)
对变量赋值
x = y
是把变量
x
指向真正的对象,该对象是变量
y
所指向的。对变量
y
的赋值
不影响
变量
x
的指向。他们是独立的根据不同的操作指向不同的地址。
Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量关联起来。
常量
所谓常量就是不能变的变量,比如常用的数学常数π就是一个常量。在Python中,通常用全部大写的变量名表示常量:
PI =
3.14159265359
但事实上
PI
仍然是一个变量,Python根本没有任何机制保证
PI
不会被改变,所以,用全部大写的变量名表示常量只是一个习惯上的用法.
最后解释一下整数的除法为什么也是精确的。在Python中,有两种除法,一种除法是
/
:
>>>
10
/
3
3.3333333333333335
/
除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:
>>>
9
/
3
3.0
还有一种除法是
//
,称为地板除,两个整数的除法仍然是整数:
>>>
10
// 3
3
整数的地板除
//
永远是整数,即使除不尽。要做精确的除法,使用
/
就可以。
因为
//
除法只取结果的整数部分,所以Python还提供一个余数运算,可以得到两个整数相除的余数:
>>>
10
%
3
1
无论整数做
//
除法还是取余数,结果永远是整数,所以,整数运算结果永远是精确的。
注意:Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在
-2147483648
-
2147483647
。
Python的浮点数也没有大小限制,但是超出一定范围就直接表示为
inf
(无限大)。
list
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。
例如:
![](https://i-blog.csdnimg.cn/blog_migrate/6947828aafe2d4efdab5d1d17cacf0f5.png)
M就是一个list
len(M)
![](https://i-blog.csdnimg.cn/blog_migrate/36dc63c0ad9046c16ad656db958c8890.png)
用索引来访问list中每一个位置的元素,记得索引是从
0
开始的:
M[0]
M[1]
![](https://i-blog.csdnimg.cn/blog_migrate/63b8e5776ce0a469821b09b76bff12e4.png)
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(M) - 1。
![](https://i-blog.csdnimg.cn/blog_migrate/bccc546f6efce657f3000bf6504e8d38.png)
如果要取最后一个元素,除了计算索引位置外,还可以用
-1
做索引,直接获取最后一个元素:
M[-1]
![](https://i-blog.csdnimg.cn/blog_migrate/57b32688ffbe7942a44e513141e26c49.png)
M[-2]
M[-3]
![](https://i-blog.csdnimg.cn/blog_migrate/65b50d0f276433d2f32d807871f8b057.png)
list是一个可变的有序表,可以往list中追加元素到末尾:
![](https://i-blog.csdnimg.cn/blog_migrate/227a72a0f3bda37c6c64d50e907c89bc.png)
也可以把元素插入到指定的位置,比如索引号为
1
的位置:
![](https://i-blog.csdnimg.cn/blog_migrate/fe11ffe9e8896ccc9b43515152142125.png)
如果该位置有数据,那么将当前数据插入该位置其他数据往后移动
![](https://i-blog.csdnimg.cn/blog_migrate/5c26f7828c94bec720cadac1df7ac89b.png)
要删除指定位置的元素,用
pop(i)
方法,其中
i
是索引位置:
例如:
M.pop(1)
![](https://i-blog.csdnimg.cn/blog_migrate/200e86e8fad6b8f8cf4d6552aba408cb.png)
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
M[1]='B'
![](https://i-blog.csdnimg.cn/blog_migrate/525ef641ed1d630329d7af1bc1535a0e.png)
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
M[1]='B'
![](https://i-blog.csdnimg.cn/blog_migrate/84501b36fbe779fb3d1a27f81286c47a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6be96efd3861df3bedc9c755e8b2fc80.png)
s = [
'python'
,
'java'
, [
'asp'
,
'php','go'
],
'C++','C'
]
![](https://i-blog.csdnimg.cn/blog_migrate/1b3a0c93eb575ac4f28079b9a4f1533f.png)
还可以拆开写
m=
[
'asp'
,
'php','go'
]
s=
[
'python'
,
'java'
, m
,
'C++','C'
]
![](https://i-blog.csdnimg.cn/blog_migrate/42d42b165f6379045a47b7324b0c38c6.png)
还可以拆开写
m=
[
'asp'
,
'php','go'
]
s=
[
'python'
,
'java'
, m
,
'C++','C'
]
![](https://i-blog.csdnimg.cn/blog_migrate/4aca8d0d44babecf3a5eaecafda9bfab.png)
获取java
s[1]
![](https://i-blog.csdnimg.cn/blog_migrate/17b89f598df71b900dfa4b0850e2aa7b.png)
获取php
![](https://i-blog.csdnimg.cn/blog_migrate/42131d1f803a5a9dc8627eabf798d09e.png)
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
![](https://i-blog.csdnimg.cn/blog_migrate/355ae54c9336565a420e359c9c9286af.png)
tuple
另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改
A=('a','b','c')
![](https://i-blog.csdnimg.cn/blog_migrate/b57399502267db4d5e5f2d2dd1ad2e69.png)
现在,A这个tuple不能变了,它也没有append(),insert()这样的方法。获取元素的方法和list是一样的,使用A[0],A[-1],但不能赋值成另外的元素。
![](https://i-blog.csdnimg.cn/blog_migrate/a8643527aabe260fccd22211df1147f0.png)
当A为一个tuple时,使用append方法追加数据会报错
![](https://i-blog.csdnimg.cn/blog_migrate/da357c163a12f273b52f2de376b4cff7.png)
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
当定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
![](https://i-blog.csdnimg.cn/blog_migrate/b333926f25c4fe17d60d04766bb28aa9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/64b1c04f2aa734b8d46019f2cead76e2.png)
定义的不是tuple,是
1
这个数!这是因为括号
()
既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是
1
。
所以,只有1个元素的tuple定义时必须加一个逗号
,
,来消除歧义:
![](https://i-blog.csdnimg.cn/blog_migrate/07a32eedcef68d9b68f80aa8db9ccaa3.png)
tuple不可变但是如果存储的数据有列表list是可变的
![](https://i-blog.csdnimg.cn/blog_migrate/01248915dbaac758b3c0e4ecd687ba84.png)
其实tuple不变变化的只能是 list里面的内容
![](https://i-blog.csdnimg.cn/blog_migrate/070556430e2bcd839e43ca5b4335b9f6.png)
tuple中指向的数据一直是不可变的,指向的list地址也不变,list中的内容可以变化,list也是一个地址,地址中的内容可以变化
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向
'a'
,就不能改成指向
'b'
,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!所有
tuple的不变应该是tuple每一个元素本身不能变。
如果tuple存一个变量,只要赋给tuple那么变量改变了tuple中的元素也不变
![](https://i-blog.csdnimg.cn/blog_migrate/8dfc3a7f2a99360905c089022ec06db2.png)
dict
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
存储:d = {
'xiaoming'
:
95
,
'xiaohong'
:
90
,
'xiaowang'
:
85
}
![](https://i-blog.csdnimg.cn/blog_migrate/b00b6858e07f90111dc28dc5e5aeb3de.png)
为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。
第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
dict就是第二种实现方式,给定一个名字,比如
'Michael'
,dict在内部就可以直接计算出
Michael
对应的存放成绩的“页码”,也就是
95
这个数字存放的内存地址,直接取出来,所以速度非常快。
这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
字典是无序的,比如加一个数据,再取出。
![](https://i-blog.csdnimg.cn/blog_migrate/5e2e2373200b92ee05259fcc7591054a.png)
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:
![](https://i-blog.csdnimg.cn/blog_migrate/9d979beed5849e4285c01b858135d4ed.png)
相当于重新赋值
如果键不存在会报错
![](https://i-blog.csdnimg.cn/blog_migrate/569d8e17aa08edba6715ccd64449b044.png)
要避免key不存在的错误,有两种办法:
![](https://i-blog.csdnimg.cn/blog_migrate/f6a6e634860b8a8de108ea5ad9346352.png)
二是通过dict提供的
get()
方法,如果key不存在,可以返回
None
,或者自己指定的value:
存在
![](https://i-blog.csdnimg.cn/blog_migrate/57427e08dff60a7663df88181d2d1faa.png)
![](https://i-blog.csdnimg.cn/blog_migrate/94b986d56ed7097b5c614fd3d67a6ab1.png)
不存在
![](https://i-blog.csdnimg.cn/blog_migrate/c8b26691bd9cd2dd30182621daca1c3b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/a0ab57274426b0a2f637198b066e2ec3.png)
返回
None
的时候Python的交互环境不显示结果。
使用自定义返回值
![](https://i-blog.csdnimg.cn/blog_migrate/89608e2504d395daee786f9542a3db56.png)
删除一个key
用
pop(key)
方法,对应的value也会从dict中删除:
![](https://i-blog.csdnimg.cn/blog_migrate/648a7e57ab79914b99d37c8d63b5aac1.png)
删除不存在的值会报错
![](https://i-blog.csdnimg.cn/blog_migrate/754145eb953034228042dcbe140e4444.png)
dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
- 查找和插入的速度极快,不会随着key的增加而变慢;
- 需要占用大量的内存,内存浪费多。
而list相反:
- 查找和插入的时间随着元素的增加而增加;
- 占用空间小,浪费内存很少。
所以,dict是用空间来换取时间的一种方法。
dict可以用在需要高速查找的很多地方,在Python代码中几乎无处不在,正确使用dict非常重要,需要牢记的第一条就是dict的key必须是
不可变对象
。
这是因为dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)。
要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key:
![](https://i-blog.csdnimg.cn/blog_migrate/84e1979ac009248e6e65f4e4607796b7.png)
#dict键值对互换
mydict={"a":1,"b":2,"c":3}
mydict_new={}
for key,val in mydict.items():
mydict_new[val]=key
print(mydict_new)
mydict={"a":'A',"b":'B',"c":'C'}
mydict_new=dict([val,key] for key,val in mydict.items())
mydict={"a":'A',"b":'B',"c":'C'}
mydict_new=
dict
(
zip
(mydict.values()
,
mydict.keys()))
print
(mydict_new)
set
set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
要创建一个set,需要提供一个list作为输入集合:
![](https://i-blog.csdnimg.cn/blog_migrate/ce4a480236ae84dbe490f8adb6a05465.png)
传入的参数
[1, 2, 3]
是一个list,而显示的
{1, 2, 3}
只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。
![](https://i-blog.csdnimg.cn/blog_migrate/c0174363fd4086d82773b348319a17d4.png)
通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
![](https://i-blog.csdnimg.cn/blog_migrate/9e13e4c624ed16f01001bc612c83059e.png)
通过remove(key)方法可以删除元素:
![](https://i-blog.csdnimg.cn/blog_migrate/2c2941495b1f3d8bcc37025528ae2c0e.png)
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
交集
![](https://i-blog.csdnimg.cn/blog_migrate/13cb2ef61ce1656b9132d5c7150f05f3.png)
并集
![](https://i-blog.csdnimg.cn/blog_migrate/d538450c02cf111f3c037ec91e63614f.png)
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。
![](https://i-blog.csdnimg.cn/blog_migrate/654e95b8a18d6a24666bf491e8c9c8d6.png)
切片
取一个list或tuple的部分元素是非常常见的操作。
定义一个list
L=[1,2,3,4,5,'a','b','c','d']
取前三个
可以使用
第一个办法
L=[1,2,3,4,5,'a','b','c','d']
print(L[0])
print(L[1])
print(L[2])
第二个办法
也可以使用循环
L=[1,2,3,4,5,'a','b','c','d']
m=[]
n=6
for i in range(n):
m.append(L[i])
print(m)
第三个办法
使用第一种办法效率太差,第二种循环比较繁琐
python提供了切片操作可以大大简化这种繁琐的操作
L=[1,2,3,4,5,'a','b','c','d']
d=L[0:6]
print(d)
L[0:6]
表示,从索引
0
开始取,直到索引
6
为止,但不包括索引
6
。即索引
1, 2, 3, 4, 5, 'a'
正好是6个元素(a的索引为5即6-1,第一个参数是从哪个索引开始,第二个是到N-1的索引结束或者理解为取第二个参数减去第一个参数的个数)切片可以大大简化繁琐的操作。
切片可以从前面取数据也可以从后面取数据
![](https://i-blog.csdnimg.cn/blog_migrate/c47a74f96223945534b9051f2ba5f929.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7178aa35363415f3374a73f629021a42.png)
迭代(iteration)
迭代:iteration
可迭代的:Iterable
迭代器:iterator
迭代相比较迭代器更加抽象,这就好比,遍历一个字典dict,用到for...in...的操作,称之为在 迭代,而这种能遍历的行为或者能迭代的行为称之为可迭代的,而迭代器是具体到迭代行为的操作者或者说是实行者,在Python中有个函数专门返回的就是迭代器对象,而这个对象可以通过next的属性对dict同样进行遍历,我们又称这种现象为迭代器
在python中一个list或tuple,要想访问其中的某个元素,可以通过下标来访问,如果想要访问所有的元素,那可以用for循环来遍历这个list或者tuple,而这种遍历就叫做迭代。
在Python中,迭代通过for..in..来完成。
python的for循环不仅可以用在
list和tuple上,还可以作用在其他可迭代的对象上
例如:
d = {
'name'
:
'Jack'
,
'age'
:
18
,
'job'
:
'Coder'
}
print
(d)
# 首先输出dict
print
(
"迭代key"
)
for
s
in
d:
print
(s)
print
(
"迭代value"
)
for
value
in
d.values():
print
(value)
print
(
'迭代key和value'
)
for
k
,
v
in
d.items():
print
(
'key:%s,value:%s'
% (k
,
v))
![](https://i-blog.csdnimg.cn/blog_migrate/9c22653916c6528a03f5e0ecaa6a0f9b.png)
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/a334ec83b720545d624108633bc1b82c.png)
for
i
in
'Hello World'
:
print
(i
,
end
=
""
)
![](https://i-blog.csdnimg.cn/blog_migrate/7dd3c27dd15073557636afbf4a415a3a.png)
输出结果
![](https://i-blog.csdnimg.cn/blog_migrate/f883419b97ce6120057815edf301afa2.png)
如果一个list、tuple或者一个字符串可以遍历,也就是有迭代的行为,称为是可以迭代的
![](https://i-blog.csdnimg.cn/blog_migrate/3f99435a885b7c0e2d32763aea29ca6c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/689172052773df0563947ce19037addf.png)
结果
![](https://i-blog.csdnimg.cn/blog_migrate/cb556c189285b80bcef83a705c30b5c2.png)
int型的数字不可迭代
字符串,list,tuple,dict,set等可以迭代
Python内置的enumerate函数可以把一个list变成 索引-元素对,这样就可以在for循环中同时迭代索引(下标)和元素(key)本身
![](https://i-blog.csdnimg.cn/blog_migrate/2e572e8be8e6d9a13c9cbe09a2664a35.png)
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/0789f5af974c9abf25a83a4d7024e75d.png)
print
(
"list变成 索引-元素对"
)
for
index
,
value
in
enumerate
([
'first'
,
'second'
,
'third'
]):
print
(index
,
":"
,
value)
print
(
"dict变成 索引-元素对"
)
for
index
,
key
in
enumerate
({
'first'
:
1
,
'second'
:
2
,
'third'
:
3
}):
print
(index
,
":"
,
key)
迭代的对象实际上是一个list,这个list的每一个元素又是一个tuple,且每个tuple对象有N个元素,这样的话,就不能单单通过 for x in list:的方式来取了,应该可以这样写,for N1,N2,N3...in list:(要保证tuple的个数相等)
![](https://i-blog.csdnimg.cn/blog_migrate/fc995e9d03a4ee687a8a76d3ad1f0ec9.png)
结果
![](https://i-blog.csdnimg.cn/blog_migrate/c23802153837572a18a1a6e603afbf61.png)
如果不相等会报错
![](https://i-blog.csdnimg.cn/blog_migrate/25def738a43d7b0fba371a31df981097.png)
结果
![](https://i-blog.csdnimg.cn/blog_migrate/412a1e1fa4adaf1b72cedb49e77e4dc2.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b851669bd41df688067f6da76d69ad7a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/ab89dc4ec9da78156e6c88d0944b6c24.png)
迭代器(Iterator)
可以被
next()
函数调用并不断返回下一个值的对象称为迭代器:
Iterator
。
可以直接作用于
for
循环的数据类型有以下几种:
一类是集合数据类型,如
list
、
tuple
、
dict
、
set
、
str
等;
一类是
generator
,包括生成器和带
yield
的generator function。
这些可以直接作用于
for
循环的对象统称为可迭代对象:
Iterable
生成器都是
Iterator
对象,但
list
、
dict
、
str
虽然是
Iterable
,却不是
Iterator
。
可以使用
isinstance()
判断一个对象是否是
Iterator
对象
from
collections
import
Iterator
isinstance
((x
for
x
in
range
(
10
)), Iterator)
isinstance
([], Iterator)
isinstance
({}, Iterator)
isinstance
(
'abc'
, Iterator)
![](https://i-blog.csdnimg.cn/blog_migrate/a8ab051bc29a6a2764533d00ae94a75f.png)
把
list
、
dict
、
str
等
Iterable
变成
Iterator
可以使用
iter()
函数
定义一个list,并通过iter获得list的迭代器对象
L = [
'python2'
,
'iter'
,
26
,
'Python3'
]
it =
iter
(L)
#获得list的迭代器对象
print
(it)
while True
:
x =
next
(it)
print
(x)
![](https://i-blog.csdnimg.cn/blog_migrate/c5ed41914bf9427669d7ed61c31ef681.png)
输出结果报错
![](https://i-blog.csdnimg.cn/blog_migrate/57c63f4894901fcf8485f1963ccb6a95.png)
这是因为next()不知道什么时候停止
将代码修改下:
L = [
'python2'
,
'iter'
,
26
,
'Python3'
]
it =
iter
(L)
#获得list的迭代器对象
while True
:
try
:
#try捕获异常
x=
next
(it)
print
(x)
except
StopIteration
:
#当捕获到迭代行为终止的时候,也就是无元素可以next的时候,终止循环
break
![](https://i-blog.csdnimg.cn/blog_migrate/c56dedb54bb42dc9f9f1cdb4e2a44581.png)
输出结果正常
![](https://i-blog.csdnimg.cn/blog_migrate/714433ad58fc33543570852f135f23e1.png)
为什么
list
、
dict
、
str
等数据类型不是
Iterator
?
因为Python的
Iterator
对象表示的是一个数据流,Iterator对象可以被
next()
函数调用并不断返回下一个数据,直到没有数据时抛出
StopIteration
错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过
next()
函数实现按需计算下一个数据,所以
Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator
甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
小结
凡是可作用于
for
循环的对象都是
Iterable
类型;
凡是可作用于
next()
函数的对象都是
Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如
list
、
dict
、
str
等是
Iterable
但不是
Iterator
,不过可以通过
iter()
函数获得一个
Iterator
对象。
Python的
for
循环本质上就是通过不断调用
next()
函数实现的,例如:
for
x
in
[
1
,
2
,
3
,
4
,
5
]:
print(x)
等价于
#
首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5
])
#
循环:
while
True:
try
:
#
获得下一个值:
x =
next(it)
except
StopIteration:
#
遇到StopIteration就退出循环
break