type
status
date
slug
summary
tags
category
icon
password
Property
Python
主要有8种数据类型:Number(数字)、Boolean(布尔值)、None(空值)、String(字符串)、List(列表)、Tuple(元组)、Set(集合)、Dictionary(字典)Number(数字)
整数
Python
可以处理任意大小的整数(包括负整数),在程序中的表示方法和数学上的写法一模一样,例如:1
,100
,-8080
,0
,等等。有时候用十六进制表示整数比较方便,十六进制用
0x
前缀和0-9,a-f表示,例如:0xff00
,0xa5b4c3d2
。对于很大的数,例如
10000000000
,很难数清0的个数。Python
允许在数字中间以_
分隔,因此写成10_000_000_000
和10000000000
是完全一样的,十六进制数也可以写成0xa1b2_c3d4
。注意:
Python
的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java
对32位整数的范围限制在-2147483648~2147483647
浮点数
浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如和 是完全相等的。
浮点数可以用数学写法,如
1.23
,3.14
,-9.01
。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代, 就是1.23e9
,或者12.3e8
,0.000012
可以写成1.2e-5
。注:
Python
的浮点数也没有大小限制,但是超出一定范围就直接表示为inf
(无限大)整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的,而浮点数运算则可能会有四舍五入的误差。
整数的除法为什么也是精确的?在Python中,有两种除法:
- 一种除法是
/
:
10/3=3.3333333333333335
/
除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:9/3=3.0
- 一种除法是
//
(地板除):
两个整数的除法仍然是整数:
10//3=3
整数的地板除
//
永远是整数,即使除不尽。要做精确的除法,使用/
就可以。因为//
除法只取结果的整数部分,所以Python还提供一个余数运算,可以得到两个整数相除的余数10%3=1
无论整数做
//
除法还是取余数,结果永远是整数布尔值
一个布尔值只有
True
、False
两种值。在Python
中,可以直接用True
、False
表示布尔值(注意大小写),也可以通过布尔运算计算出来:布尔值可以用
and
、or
和not
运算:and
:与运算,只有所有都为True
,结果才是True
or
:或运算,只要其中有一个为True
,结果就是True
not
:非运算,是一个单目运算符,把True
变成False
,False
变成True
空值
None
是一个特殊的常量,表示空值,其和False
,0
以及空字符串不同,它是一个特殊Python
对象, None
的类型是NoneType
。字符串
字符串是以单引号
'
或双引号"
括起来的任意文本,比如'abc'
,"xyz"
。''
或""
本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'
只有a
,b
,c
这3个字符。如果'
本身也是一个字符,那就可以用""
括起来,比如"I'm OK"
包含的字符是I
,'
,m
,空格,O
,K
这6个字符。如果字符串内部既包含
'
又包含"
,可以用转义字符\
来标识。转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
Python
允许用r''
表示''
内部的字符串默认不转义:如果字符串内部有很多换行,用
\n
写在一行里不好阅读,可以用'''...'''
的格式表示多行内容list
Python内置的一种数据类型是列表:list。
list
是一种有序的集合,可以随时添加和删除其中的元素。创建列表
- 使用 [ ] 创建列表
创建一个列表,只需要把逗号分隔的不同数据项使用方括号
[]
括起来即可:- 使用
list()
函数创建(转换为)列表
可以使用
list()
函数将字符串、元组、字典和集合等其他类似对象转换为列表:list
里面的元素的数据类型也可以不同,比如:L = ['Apple', 123, True]
嵌套列表:
list
元素也可以是另一个list
如果一个
list
中一个元素也没有,就是一个空的list
,长度为0访问列表
下标索引访问:分为两大类,即正向索引和反向索引,格式为
list_name[i]
,其中,list_name
表示列表名,i
表示索引值,i
可以是正数(正向索引)也可以是负数(反向索引)。切片访问:使用切片访问列表的格式为
list_name[strat:end:step]
,其中,start
表示起始索引,end
表示结束索引,step
表示步长。[start:end]
是左闭右开区间。for循环遍历列表:
检查项目是否存在:使用
in
关键字更改列表值
列表连接(合并)/复制:
+
连接(合并) *
复制内置方法
方法 | 描述 |
append(obj) | 在列表末尾添加新的对象 |
insert(index, obj) | 在指定位置添加元素 |
extend(seq) | 将列表元素(或任何可迭代的元素)添加到当前列表的末尾 |
count(obj) | 统计某个元素在列表中出现的次数 |
index(obj) | 返回具有指定值的第一个元素的索引 |
sort( key=None, reverse=False) | 对原列表进行排序 |
copy() | 复制列表 |
reverse() | 颠倒列表的顺序 |
pop([-1]) | 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值 |
remove(obj) | 移除列表中某个值的第一个匹配项 |
clear() | 清空列表 |
Python中remove,del以及pop之间的区别
remove,del以及pop都可以用于删除列表、字符串等里面的元素,但是具体用法并不相同。
- remove是剔除第一个匹配的值。
- del是通过索引来删除当中的元素。
- pop是通过索引来删除当中的元素,并且返回该元素;若括号内不添加索引值,则默认删除最后一个元素。
tuple
另一种有序列表叫元组:
tuple
。tuple
和list
非常类似,但是tuple
一旦初始化就不能修改,比如同样是列出同学的名字:现在,
classmates
这个tuple
不能变了,它也没有append()
,insert()
这样的方法。其他获取元素的方法和list
是一样的,可以正常地使用classmates[0]
,classmates[-1]
,但不能赋值成另外的元素。不可变的
tuple
有什么意义?因为tuple
不可变,所以代码更安全。如果可能,能用tuple
代替list
就尽量用tuple
。tuple
的陷阱:定义一个tuple
时,元素就必须被确定下来要定义一个只有1个元素的
tuple
,如果这么定义:定义的不是
tuple
,是1
这个数!这是因为括号
()
既可以表示tuple
,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python
规定这种情况下,按小括号进行计算,计算结果自然是1
所以,只有1个元素的
tuple
定义时必须加一个逗号,
,来消除歧义:互换变量有不用创建临时变量的方法
在Python中,当我们想要互换两个变量的值或将列表中的两个值交换时,可以使用如下的格式进行,不需要创建临时变量:
这么做的原理是什么呢?
首先一般情况下Python是从左到右解析一个语句的,但在赋值操作的时候,因为是右值具有更高的计算优先级,所以需要从右向左解析。对于上面的代码,它的执行顺序如下:
先计算右值 (这里是简单的原值,但可能会有表达式或者函数调用的计算过程), 在内存中创建tuple,存储分别对应的值;计算左边的标识符,元组被分别分配给左值,通过解包(unpacking),元组中第一个标示符对应的值 ,分配给左边第一个标示符,元组中第二个标示符对应的值,分配给左边第二个标示符,完成了和的值交换。
“可变的”tuple
这个
tuple
定义的时候有3个元素,分别是'a'
,'b'
和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?先看看定义的时候
tuple
包含的3个元素:当把
list
的元素'A'
和'B'
修改为'X'
和'Y'
后,tuple
变为:表面上看,
tuple
的元素确实变了,但其实变的不是tuple
的元素,而是list
的元素。tuple
一开始指向的list
并没有改成别的list
,所以,tuple
所谓的“不变”是说:tuple的每个元素,指向永远不变。即指向'a'
,就不能改成指向'b'
,指向一个list
,就不能改成指向其他对象,但指向的这个list
本身是可变的!怎么创建一个内容也不变的
tuple
?那就必须保证tuple
的每一个元素本身也不能变。Python中列表和元组的区别
- 列表是可变的,在创建之后可以对其进行任意的修改。
- 元组是不可变的,元组一旦创建,便不能对其进行更改,可以元组当作一个只读版本的列表。
- 元组无法复制。
- Python将低开销的较大的块分配给元组,因为它们是不可变的。对于列表则分配小内存块。与列表相比,元组的内存更小。当你拥有大量元素时,元组比列表快。
dict
Python
内置了字典:dict
的支持,dict
全称dictionary
,在其他语言中也称为map
,使用键-值(key-value)存储,具有极快的查找速度。假设要根据同学的名字查找对应的成绩,如果用list
实现,需要两个list
:给定一个名字,要查找对应的成绩,就先要在
names
中找到对应的位置,再从scores
取出对应的成绩,list
越长,耗时越长如果用
dict
实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢:为什么
dict
查找速度这么快?因为
dict
的实现原理和查字典是一样的,假设字典包含了1万个汉字,要查某一个字:- 一个办法是把字典从第一页往后翻,直到找到想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。
- 第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。
dict
就是第二种实现方式,给定一个名字,比如'Michael'
,dict
在内部就可以直接计算出Michael
对应的存放成绩的“页码”,也就是95
这个数字存放的内存地址,直接取出来,所以速度非常快。这种
key-value
存储方式,在放进去的时候,必须根据key算出value的存放位置,这样取的时候才能根据key直接拿到value。把数据放入
dict
的方法,除了初始化时指定外,还可以通过key放入:务必注意:
dict
内部存放的顺序和key
放入的顺序是没有关系的。和
list
比较,dict
有以下几个特点:- 查找和插入的速度极快,不会随着
key
的增加而变慢
- 需要占用大量的内存,内存浪费多
而
list
相反:- 查找和插入的时间随着元素的增加而增加
- 占用空间小,浪费内存很少
所以,
dict
是用空间来换取时间的一种方法。dict
可以用在需要高速查找的很多地方,需要牢记的第一条就是dict
的key
必须是不可变对象。因为
dict
根据key
来计算value
的存储位置,如果每次计算相同的key
得出的结果不同,那dict
内部就完全混乱了。这个通过key
计算位置的算法称为哈希算法(Hash)。要保证
hash
的正确性,作为key的对象就不能变。在Python
中,字符串、整数等都是不可变的,可以放心地作为key
。而list
是可变的,就不能作为key
:Python中dict(字典)的底层结构
Python的dict(字典)为了支持快速查找使用了哈希表作为底层结构,哈希表平均查找时间复杂度为O(1)。CPython 解释器使用二次探查解决哈希冲突问题。
set
set
和dict
类似,也是一组key
的集合,但不存储value
。由于key
不能重复,所以在set
中,没有重复的key
。要创建一个
set
,需要提供一个list
作为输入集合:注意,传入的参数
[1, 2, 3]
是一个list
,而显示的{1, 2, 3}
只是告诉你这个set
内部有1,2,3这3个元素,显示的顺序也不表示set是有序的重复元素在
set
中自动被过滤:set
和dict
的唯一区别仅在于没有存储对应的value
,但是set
的原理和dict
一样,所以同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set
内部“不会有重复元素”。不可变对象
可变对象与不可变对象的区别在于对象本身是否可变
- 可变对象:list(列表) dict(字典) set(集合)
- 不可变对象:tuple(元组) string(字符串) int(整型) float(浮点型) bool(布尔型)
a
是变量,'abc'
才是字符串对象!对象a
的内容是'abc'
,其实是指a
本身是一个变量,它指向的对象的内容才是'abc'
:当调用
a.replace('a', 'A')
时,实际上调用方法replace
是作用在字符串对象'abc'
上的,而这个方法虽然名字叫replace
,但却没有改变字符串'abc'
的内容。相反,replace
方法创建了一个新字符串'Abc'
并返回,如果用变量b
指向该新字符串,就容易理解了,变量a
仍指向原有的字符串'abc'
,但变量b
却指向新字符串'Abc'
了:所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。