python基础--数据类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python基础--数据类型相关的知识,希望对你有一定的参考价值。
当语句以冒号:结尾时,缩进的语句视为代码块。
缩进有利有弊。好处是强迫你写出格式化的代码,但没有规定缩进是几个空格还是Tab。按照约定俗成的管理,应该始终坚持使用4个空格的缩进。
Python程序是大小写敏感的,如果写错了大小写,程序会报错。
数据类型
计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频、网页等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种:
数据类型
数字(整形,长整形,浮点型,复数)
字符串
列表
元组
字典
集合
整数
Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等。
计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用0x前缀和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。
浮点数
浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x109和12.3x108是完全相等的。浮点数可以用数学写法,如1.23,3.14,-9.01,等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x109就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。
整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
字符串
字符串是以单引号‘或双引号"括起来的任意文本,比如‘abc‘,"xyz"等等。请注意,‘‘或""本身只是一种表示方式,不是字符串的一部分,因此,字符串‘abc‘只有a,b,c这3个字符。如果‘本身也是一个字符,那就可以用""括起来,比如"I‘m OK"包含的字符是I,‘,m,空格,O,K这6个字符。
如果字符串内部既包含‘又包含"怎么办?可以用转义字符\来标识,比如:
‘I\‘m \"OK\"!‘
表示的字符串内容是:
I‘m "OK"!
转义字符\可以转义很多字符,比如\n表示换行,\t表示制表符,字符\本身也要转义,所以\表示的字符就是\,可以在Python的交互式命令行用print()打印字符串看看:
print(‘I\‘m ok.‘)
效果如图所示:
print(‘I\‘m learning\nPython.‘)
print(‘\\n\‘)
如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r‘‘表示‘‘内部的字符串默认不转义
print(‘\\t\‘)
print(r‘\\t\‘)
如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用‘‘‘...‘‘‘的格式表示多行内容
注意在输入多行内容时,提示符由>>>变为...,提示你可以接着上一行输入,注意...是提示符,不是代码的一部分
当输入完结束符```和括号)后,执行该语句并打印结果。
如果写成程序并存为.py文件,就是:
print(‘‘‘line1
line2
line3‘‘‘)
布尔值
布尔值和布尔代数的表示完全一致,一个布尔值只有True、False两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来:
布尔值可以用and、or和not运算。
and运算是与运算,只有所有都为True,and运算结果才是True:
or运算是或运算,只要其中有一个为True,or运算结果就是True:
not运算是非运算,它是一个单目运算符,把True变成False,False变成True:
布尔值经常用在条件判断中
空值
空值是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)
加单引号双引号的都是字符串
变量在内存中的存储形式:
在python中, 每一个变量在内存中创建,我们可以通过变量来查看内存中的值
在python中通过指针改变变量的值
x = 1 说明x指向了内存中存储为1的地址,地址是1767137504
y = 2 说明y指向了内存中存储为2的地址,地址是1767137536
也就是说在执行x = 4,y = 5之后,x,y分别指向了不同的地址
当执行 x = y之后
x指向了y所指向的内存了,它们都指向同一块内存,跟c里面的指针一样
linux 下
(好像linux(64bit ubuntu)和windows(64bit windows10)占用的内存大小不一样)
在python中,一开始初始化存储在内存的东西是不可以改变的,我们所能改变的只是它的指向。
示意图为
可以看出x和1的地址是一个地址,y的地址和2是一个地址。
所以
执行 x = 1,解释器创建了整数和变量x,并把x指向1所在的内存地址:
执行x = y,解释器创建了变量y,并把y指向x指向a的内存地址
如果将x重新赋值abc x=‘abc‘,那么解释器创建了字符串‘abc‘,并把x的指向改为‘abc‘所在的内存地址,但y并没有更改
对变量赋值x = y是把变量x指向真正的对象,该对象是变量y所指向的。对变量y的赋值不影响变量x的指向。他们是独立的根据不同的操作指向不同的地址。
Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量关联起来。
常量
所谓常量就是不能变的变量,比如常用的数学常数π就是一个常量。在Python中,通常用全部大写的变量名表示常量:
PI = 3.14159265359
但事实上PI仍然是一个变量,Python根本没有任何机制保证PI不会被改变,所以,用全部大写的变量名表示常量只是一个习惯上的用法.
最后解释一下整数的除法为什么也是精确的。在Python中,有两种除法,一种除法是/:
>> 10 / 33.3333333333333335
/除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:
>> 9 / 33.0
还有一种除法是//,称为地板除,两个整数的除法仍然是整数:
>> 10 // 33
整数的地板除//永远是整数,即使除不尽。要做精确的除法,使用/就可以。
因为//除法只取结果的整数部分,所以Python还提供一个余数运算,可以得到两个整数相除的余数:
>> 10 % 31
无论整数做//除法还是取余数,结果永远是整数,所以,整数运算结果永远是精确的。
注意:Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647。
Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大)。
list
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。
例如:
M就是一个list
用len()函数可以获得list元素的个数:
len(M)
用索引来访问list中每一个位置的元素,记得索引是从0开始的:
M[0]
M[1]
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(M) - 1。
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
M[-1]
获取倒数第2个、倒数第3个:
M[-2]
M[-3]
list是一个可变的有序表,可以往list中追加元素到末尾:
M.append(‘d‘)
也可以把元素插入到指定的位置,比如索引号为1的位置:
M.insert(1, ‘e‘)
如果该位置有数据,那么将当前数据插入该位置其他数据往后移动
要删除指定位置的元素,用pop(i)方法,其中i是索引位置:
例如:
M.pop(1)
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
M[1]=‘B‘
list里面的元素的数据类型也可以不同,比如:
L = [‘A‘, 123, True]
list元素也可以是另一个list,比如:
s = [‘python‘, ‘java‘, [‘asp‘, ‘php‘,‘go‘], ‘C++‘,‘C‘]
还可以拆开写
m=[‘asp‘, ‘php‘,‘go‘]
s=[‘python‘, ‘java‘, m, ‘C++‘,‘C‘]
获取java
s[1]
获取php
s可以看成是一个二维数组
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
tuple
另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改
A=(‘a‘,‘b‘,‘c‘)
现在,A这个tuple不能变了,它也没有append(),insert()这样的方法。获取元素的方法和list是一样的,使用A[0],A[-1],但不能赋值成另外的元素。
当A为一个tuple时,使用append方法追加数据会报错
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
当定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
定义一个只有1个元素的tuple,如果这么定义:
定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
tuple不可变但是如果存储的数据有列表list是可变的
其实tuple不变变化的只能是 list里面的内容
tuple中指向的数据一直是不可变的,指向的list地址也不变,list中的内容可以变化,list也是一个地址,地址中的内容可以变化
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向‘a‘,就不能改成指向‘b‘,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!所有tuple的不变应该是tuple每一个元素本身不能变。
如果tuple存一个变量,只要赋给tuple那么变量改变了tuple中的元素也不变
dict
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
dict根据键值对来获取数据,存储的也是键值对
存储:d = {‘xiaoming‘: 95, ‘xiaohong‘: 90, ‘xiaowang‘: 85}
获取:d[‘xiaoming‘]
为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。
第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
dict就是第二种实现方式,给定一个名字,比如‘Michael‘,dict在内部就可以直接计算出Michael对应的存放成绩的“页码”,也就是95这个数字存放的内存地址,直接取出来,所以速度非常快。这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
字典是无序的,比如加一个数据,再取出。
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:
相当于重新赋值
如果键不存在会报错
要避免key不存在的错误,有两种办法:
一是通过in判断key是否存在:
二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:
存在
不存在
返回None的时候Python的交互环境不显示结果。
使用自定义返回值
删除一个key
用pop(key)方法,对应的value也会从dict中删除:
删除不存在的值会报错
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:
#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作为输入集合:
传入的参数[1, 2, 3]是一个list,而显示的{1, 2, 3}只是告诉你这个set内部有1,2,3这3个元素,显示的顺序也不表示set是有序的。。
重复元素在set中自动被过滤:
通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
通过remove(key)方法可以删除元素:
set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:
交集
并集
set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。
把list放入set,会报错。
切片
取一个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的索引结束或者理解为取第二个参数减去第一个参数的个数)切片可以大大简化繁琐的操作。
切片可以从前面取数据也可以从后面取数据
迭代(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))
输出结果
字符串也可以进行迭代,迭代出每个字符:
for i in ‘Hello World‘:
print(i,end="")
输出结果
可迭代的(Iterable)
如果一个list、tuple或者一个字符串可以遍历,也就是有迭代的行为,称为是可以迭代的
结果
int型的数字不可迭代
字符串,list,tuple,dict,set等可以迭代
Python内置的enumerate函数可以把一个list变成 索引-元素对,这样就可以在for循环中同时迭代索引(下标)和元素(key)本身
输出结果:
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的个数相等)
结果
如果不相等会报错
结果
迭代器(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)
把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)
输出结果报错
这是因为next()不知道什么时候停止
将代码修改下:
L = [‘python2‘,‘iter‘,26,‘Python3‘]
it = iter(L) #获得list的迭代器对象
while True:
try:#try捕获异常
x=next(it)
print(x)
except StopIteration:#当捕获到迭代行为终止的时候,也就是无元素可以next的时候,终止循环
break
输出结果正常
为什么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
以上是关于python基础--数据类型的主要内容,如果未能解决你的问题,请参考以下文章