3 Python 基本数据类型

368 阅读39分钟

❤ 摘要

本章主要讲解python的数据类型。

数据类型分为不可变数据类型可变数据类型

知识点

  • 不可变数据类型:
  1. 数字
  2. 字符串
  3. 元祖
  • 可变数据类型:
  1. 列表
  2. 集合
  3. 字典

▶️ 基本数据类型

在 Python 中,数据类型分为不可变数据类型可变数据类型

  • 不可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。数字、字符串、元组属于不可变数据类型。

  • 可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。列表、集合、字典属于可变数据类型。

我们可以通过内置函数 type() 查看对象的类型。通过内置函数 id() 查看对象的内存地址

1. 数字

在 Python 中存在三种不同的数字类型: 整数、浮点数、复数,数字类型用于存储数值,属于不可变数据类型

我们进入 Python 交互模式来验证一下:

a = 5
type(a)
id(a)
a = 6
id(a)

运行效果如下:

图片.png

可以看到,变量 a 是整数类型,当 a 的值发生了变化,内存地址就会改变。


1.1 整数类型

整数类型(int)通常被称为是整型或整数,包括正整数和负整数,不带小数点。Python 3 中,整型具有无限的精度,就是说没有大小限制。Python3 中没有 Python 2 中的 long 类型,而是将 long 类型和 int 类型整合到了 int 类型。

1.2 整数-布尔型

布尔类型(bool)也叫布尔、布尔型,是整型的子类型。布尔类型是两个常量对象 FalseTrue,它们用来表示逻辑上的真假。内置函数 bool() 可被用来将任意值转换为布尔值。

在数字运算时,布尔类型相当于整数 0(False)和 1(True)。

我们可以做个实验,用 bool 类型和数字进行简单的运算。

True + 5
False * 3

运行效果如下:

图片描述


1.3 浮点型 float

浮点数类型通常也叫浮点型,是使用 C 语言的 double 类型来实现,可以近似表示数学中的实数。

浮点型由整数部分与小数部分组成,也可以使用科学计数法表示(1.5e2 = 1.5 x 10² = 150.0)

需要注意的是,像 1.12.2 这样的数字因为在二进制浮点中没有精确的表示,导致浮点数运算时有时候会出现意想不到的结果,比如下面的演示:

运行效果如下:

图片描述

这就像一个陷阱一样,虽然很多编程语言也会有同样的情况。

❤️ 求近似值 round()

这时候你可能会想到求近似值,Python 内置函数 round() 可以获得近似值。其语法为 round(number, ndigits),可选参数 ndigits 是指小数点后几位精度,为空时会返回最接近的整数。

我们看两个例子:

a = 1.1 + 2.2
round(a)
round(a, 2)

运行效果如下:

图片描述

虽然也能获得正确结果,但你也不能确定到底小数点后几位精度才会获得正确结果。而且 round() 函数通常情况下能实现四舍五入,但有时候也会产生让你抓狂的结果。

运行效果如下:

图片描述

这个情况也是因为十进制小数不能正确被浮点数表示。

你可能想问,浮点数到底有没有办法获得正确的结果?

❤️ 正确的浮点数运算 decimal

这时候,就该 decimal 模块闪亮登场了。decimal 模块就可以实现快速正确的十进制浮点数计算,让我们得到正确的计算结果。

下面看一个例子:

from decimal import Decimal

a = Decimal('1.1') + Decimal('2.2')
float(a)

可以看到,我们得到了正确的结果。这里需要注意的是 Deciaml() 必须是字符串形式的数字。

运行效果如下:

图片描述


1.4 复数类型

复数由实数部分和虚数部分构成,可以用 a + bj,或者 complex(a,b) 表示,复数的实部 a 和虚部 b 都是浮点型。要从一个复数 z 中提取这两个部分,可使用 z.realz.imag

依次运行下面语句,感受一下:

a = 5 +6j
type(a)
a.real
a.imag
b = complex(2,3)
b
b.real
b.imag

运行效果如下:

图片描述

1.5 数字类型转化

我们可以使用构造函数 int()、 float() 和 complex() 分别构造特定类型的数字。

int() 函数

int() 函数在将数字类型转换为整数时,参数为空返回 0 ;十进制整数返回本身;浮点数采用向下取整;二进制整数和十六进制整数都会返回对应的十进制整数。

int()    #参数为空
int(1)    #十进制整数
int(1.3)    #浮点数
int(1.9)    #浮点数
int(0b101)    #二进制整数
int(0x32)    #十六进制整数

运行效果如下:

图片描述


int() 函数在将字符串作为参数时,该字符串中的数字只能是整数。其他进制整数在转换时需要指定可选参数 base,默认是 10(十进制),另外可以选择 0 或者 2-36,指定 0 会根据书写方式自动判断。

int('10')    #字符串内是十进制整数
int('0b101',base=0)    #字符串内是二进制整数
int('0x32',base=0)    #字符串内是十六进制整数
int('0b101',base=2)    #字符串内是二进制整数
int('0x32',base=16)    #字符串内是十六进制整数

运行效果如下:

图片描述

需要注意的是,int() 函数在将字符串作为参数时,字符串内不能是浮点数形式。

a = '1.5'
int(a)

运行效果如下:

图片描述

那如果有一个字符串类型的数字 '1.3' 该如何转换成整数类型呢?


float() 函数

float() 可以将数字或者字符串转换到一个浮点数类型。

float(1)
float(1.5)
float('1')
float('1.5')

运行效果如下:

图片描述

前面我们提到,int() 函数不能将字符串类型的浮点数作为参数,那我们如何将字符串 '3.1415926' 转换为整数类型呢?

首先使用 float() 函数将字符串类型转换为浮点数类型,然后使用 int() 函数将浮点数转换为整数类型。

a = float('3.1415926')
b = int(a)
print(b)

运行效果如下:

图片描述

int() 函数和 float() 函数结合一下:

int(float('3.1415926'))

运行效果如下:

图片描述


complex() 函数

complex(x) 将 x 转换到一个复数,实数部分为 x,虚数部分为 0。

complex(5)

运行效果如下:

图片描述

complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。

complex(5,3)

运行效果如下:

图片描述


1.6 数字运算

Python 解释器其实完全可以作为一个计算器来使用,前面章节我们也进行过好几次简单的计算。接下来我们将演示 Python 中常用的数字运算。

print(3 + 5)    #加法
print(9 - 3)    #减法
print(3 * 5)    #乘法
print(10 / 3)    #除法
print(10 // 3)    #整除,向下取整
print(10 % 3)    #取余,除法运算之后返回余数
print(2 ** 10)    #乘方,2 的 10 次方

运行效果如下:

图片描述


Python 完全支持混合运算当一个二元算术运算符的操作数有不同数值类型时,"较窄"类型的操作数会拓宽到另一个操作数的类型,其中整数比浮点数窄,浮点数比复数窄。不同类型的数字之间的比较,同比较这些数字的精确值一样。

a = 5
b = 3.1
c = complex(3)
d = a + b
e = a + c
type(d)
type(e)

运行效果如下:

图片描述

比如这里的a+b,整数比浮点数窄,最终是浮点型。

图片.png

浮点型比复数窄,最终是复数

图片.png


2. 字符串

在 Python 中处理文本数据时使用 str 对象,通常称为 字符串。 字符串是 Python 中最常用的数据类型。

字符串是由 Unicode 编码构成的不可变数据类型

上节提到,我们可以通过内置函数 type() 查看对象的类型。通过内置函数 id() 查看对象的内存地址。

接下来,我们在终端进入 Python 交互模式来验证一下:

图片.png

字符串变化,地址变化,是 不可变数据类型

2.1 字符串索引

字符串的本质是字符的有序组合,在 Python 中,没有单字符类型,统一都是字符串类型。

字符串可以通过索引(下标访问)获取到对应位置的字符。你可以把索引理解成序号,不过和大部分编程语言一样,索引是从 0 开始的,在 字符串长度-1 的位置结束,如下图:

图片.png

跟c语言的有些类似,从0开始到len-1结束,总共还是len长度。


我们进入 Python 交互模式继续实验。

a = "Hello"
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]    #此处因为超出范围,会报错。

图片.png

逆方向索引

除了正方向的正索引,Python 还支持逆方向的负索引。

图片描述

我们在 Python 交互环境来实验一下:

a = "Hello"
a[-5]
a[-4]
a[-3]
a[-2]
a[-1]

图片.png

因为字符串是不可变数据类型,我们如果给某个索引位置赋值就会报错。

a = "12345"
a[0] = "a"

图片.png

所以不能直接赋值。


2.2 字符串切片

切片的基本语法

除了索引,Python 还支持切片。索引用于获取单个字符,切片用于获取子字符串。

图片描述

切片的基本语法是 string[start:end],start 默认是 0,end 默认到行尾。切片的操作“包头不包尾”,我们下面举例说明。

a = "Hello"
a[0:3]    #返回索引 012 位置的字符
a[2:4]    #返回索引 23 位置的字符
a[:4]    #start参数默认是0,所以返回索引 0123 位置的字符
a[3:]    #end 默认到行尾,返回索引 34 位置的字符
a[-3:-1]    #返回索引 -3-2 位置的字符
a[-2:-1]    #返回索引 -2 位置的字符
a[-2:]    #end 默认到行尾,返回索引 -2-1 位置的字符
a[::]    #start 默认 0end 默认到行尾,所以返回整个字符串

运行效果如下:

图片描述

大致你按上面图片上的划分好。


切片的步长

切片中其实还有第三个参数 步长,语法是 string[start:end:step]

步长可以是正数,也可以是负数,但不能为 0 。

当步长为负数时,start 的默认值是行尾,end 默认值是 0 。但 start 和 end 依旧满足“包头(start)不包尾(end)”,区别只是 start 比 end 的索引值数字大。

我们通过下面的例子,来理解一下步长的使用。

a = "123456789"
a[0:9:2]    #将全部字符串以步长 2 选取。
a[2:7:3]    #将索引 2 到索引 7 之间的字符,以步长 3 选取。
a[::-1]    #步长 -1 可实现对字符串的翻转,此处表示对整个字符串翻转
a[5:1:-1]    #步长 -1,将索引 5 到 索引 1 之间的字符翻转

运行效果如下:

图片描述


越界问题

另外,切片会自动处理索引 end 的越界问题。

a = "123456"
a[2:10]
a[-3:-100:-1]

运行效果如下:

图片描述

不用考虑越界问题。


2.3 转义字符

在很多编程语言、数据格式、通信协议中,通常会使用转义字符来表示一些特殊的字符。比如 URL 链接中会使用 % 进行转义,而 C 语言、Java、Python 都是使用反斜杠(\)进行转义


续行符 \

print('hello \
world!')

运行效果如下:

图片描述


引号 '"

在 Python 中,单引号字符串中如果使用单引号可能会出现解释器无法识别的问题,所以我们就需要使用转义字符对字符串中的单引号进行转义。

print('It's OK!') #'s单引号无法识别
print('It\'s OK!') # 单引号' \转义

运行如下:

图片.png

可以看到,不转义会报错,而转义之后不会报错。双引号也是一样的。


响铃 \a

print("\a")

因为实验环境不支持发声,大家可以在自己的电脑上尝试。

运行效果如下:

图片.png

可以看到,运行之后标签上出现了响铃的图标。

退格(Backspace) \b

退格符会将光标退回前一个字符,不会删除光标后面的字符。但当退格符后边有新的字符时,将会覆盖退回的那个字符。

print('hello  \bworld !')    # 此处会退格后继续书写
print('hello world !\b')    #此处退格符后面没有内容,所以没有变化。

图片.png

换行 \n

换行(\n)是光标到下一行。

print("Hello World!\nHello World!")

运行效果如下:

图片描述

回车 \r

回车(\r): 回到一旧行(当前行)的开头。(即光标目前所在的行为旧行)

print("123456\rs")

光标回到本行开头位置续写s

图片.png

图片.png


横向制表符 \t

print("Hello\tWorld!")

运行效果如下:

图片描述

纵向制表符 \v

print("Hello\vWorld!")

运行效果如下:

图片描述

八进制

表示字符串ASCII表需要转换为十进制:比如110十进制表示72,对应H

1~3位八进制数据所表示的 ASCII 字符。

print("\110\145\154\154\157\40\127\157\162\154\144\41")

运行效果如下:

图片描述

十六进制

4位十六进制数据所表示的字符。

print("\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21")

运行效果如下:

图片描述

避免转义 \

当我们遇到上述特殊字符但不需要转义时,我们可以在特殊字符前面加上反斜杠 \ 避免转义。比如我们有一个路径 D:\tt\no\reseach

print("D:\tt\no\reseach")    #默认输出的效果 \可能会被识别为转义符号
print("D:\\tt\\no\\reseach")    #\避免转义之后

运行效果如下:

图片描述

可以看到,默认输出的结果简直面目全非,而加上反斜杠 \ 避免转义之后,输出了我们想要的结果。


2.4 字符串运算符

此处我们介绍一些字符串常用的运算符操作。

其中 innot in 操作具有与比较>、< 操作相同的优先级。 + (拼接) 和 * (重复) 操作具有与对应数值运算相同的优先级。

in 操作符

如果字符串包含指定字符就返回 True,否则返回 False。

'e' in 'Hello'
'f' in 'Hello'

运行效果如下:

图片描述


not in 操作符

如果字符串不包含指定字符就返回 True,否则返回 False。

'e' not in 'Hello'
'f' not in 'Hello'

运行效果如下:

图片描述


字符串拼接(+

字符串可以使用 + 将两段字符串进行拼接。

'Hello' + ' World'    # World 前面有个空格
'明天是' + '周六'

运行效果如下:

图片描述


重复运算符(*

字符串和数字 n 相乘表示将字符串重复 n 次。

'=' * 15 + '测试' + '=' * 15
'Hello ' * 4

运行效果如下:

图片描述


原始字符串(r)

原始字符串,是在引号前面加上 rR,这样遇到特殊字符就不会转义,而是普通输出。

print("C:\Windwos\no\reseach")    #默认输出的效果
print(r"C:\Windwos\no\reseach")    #原始字符串效果

运行效果如下:

图片描述


2.5 字符串格式化

为了解决数字和字符串拼接错误

前面我们学习了使用 + 运算符实现对字符串的拼接,但是当如果我们想把数字和字符串拼接到一起时就会报错。

'今年是' + 2021 + '年'

运行效果如下:

图片描述

当然,我们可以使用 str() 函数将数字转换为字符串格式。

'今年是' + str(2021) + '年'

运行效果如下:

图片描述

这样虽然能解决问题,但是当我们有多个需要转换的字符,就让整个字符串变得很混乱。接下来我们就开始学习更好的解决方案,字符串格式化。


f-string 格式化

f-string 是 Python 在 Python 3.6 引入的格式化方案,是在普通字符串前面加上 fF,然后在字符串中使用大括号( {})引入变量或表达式,这种写法让字符串的书写变得简洁优雅。。

year = 2021
month = 4
day = 1
f"今天是{year}年{month}月{day}日"

运行效果如下:

图片描述

格式说明符

在上面的基础用法之外,还可以使用可选的格式说明符,写在冒号(:)后面。

浮点数说明符f

.2f 是指小数点后两位小数,f 是定点表示法,在没有指定精度时,会对浮点数采用小数点后 6 位有效数位的精度。

pi = 3.1415
f'圆周率保留两位小数是:{pi:.2f}'    #指定精度
f'圆周率保留两位小数是:{pi:f}'    #未指定精度

运行效果如下:

图片描述

使用四舍五入取精度:

图片.png


最小字符宽度(列对齐) :整数

如果冒号(:)后面是一个整数,是为该字段设置最小字符宽度,常用于列对齐:

name1 = 'Bob'
age1 = 20
name2 = 'John'
age2 = 25
print(f'{name1:6}=>{age1:6}\n{name2:6}=>{age2:6}')

运行效果如下:

图片描述

可以看到,因为限定了字符宽度为 6,不够的部分就会用空格进行填充,从而实现对齐效果。

如果是数字,还可以指定用 0 填充,就会在数字前面加 0。

total = 2000
print(f'金额总数:{total:08} 元')

运行效果如下:

图片描述


千位分隔符

数字还可以使用 _ 或者 , 作为千位分隔符,让数字的阅读更加方便。

f'{100000000000}'
f'{100000000000:_}'
f'{100000000000:,}'

运行效果如下:

图片描述

另外 _b, _o, _x 可以让二进制、八进制、十六进制每隔 4 个数码进行分隔。

f'{0b10000000:_b}'    #二进制分隔表示
f'{128:_b}'        #十进制数会先转二进制,然后分隔表示
f'{10000:_o}'    #十进制数转八进制,然后分隔表示
f'{12800000:_x}'    #十进制数会先转十六进制,然后分隔表示

运行效果如下:

图片描述


百分比

可以使用 % 将数字转换为百分比形式。和 f 转换一样,不指定精度会按小数点后 6 位精度。

f'{0.25:%}'        #不指定精度
f'{0.25:.2%}'    #指定精度

运行效果如下:

图片描述


其他修饰符 !a !s !r

还有一些修饰符可以在格式化前转换值。!a 对应 ascii() 函数,!s 对应 str() 函数,!r 对应 repr() 函数。

name = '苏轼'
print(f'{name!a}')
print(f'{name!s}')
print(f'{name!r}')

运行效果如下:

图片描述

参考:


时间类型格式化

import datetime
d = datetime.datetime(2021, 10, 1, 8, 15, 58)
'{:%Y-%m-%d %H:%M:%S}'.format(d)

运行效果如下:

图片描述


format 格式化

位置引用

format 格式化是将传递给 format 方法的对象传递到花括号内,使用如下:

print('We are the {} who say "{}!"'.format('knights', 'Ni'))

还可以在花括号中加上的数字表示传递给 str.format() 方法的对象所在的位置。

print('{0} and {1}'.format('spam', 'eggs'))
print('{1} and {0}'.format('spam', 'eggs'))

运行效果如下:

图片描述


关键字引用

在位置引用之外,还可以使用关键字引用。

print('他今年 {age} 岁,在{city}工作。'.format(age=25, city='北京'))

运行效果如下:

图片描述


格式化方式

对于字符或者数字的格式限定和上面的 f-string 基本类似,只是需要将需要引用的值放到 format() 方法内。需要注意的是 format() 方法不支持表达式。

pi = 3.1415926
'圆周率是:{:.2f}'.format(pi)

运行效果如下:

图片描述


% 格式化

% 运算符也可用于字符串格式化,不过因为有很多怪异特性,导致很多错误,官方已经不推荐使用,我们这里只做简单介绍。

'%s %s'%('Hello','World')
'圆周率是:%.2f'%(3.1415926)

运行效果如下:

图片描述


2.6 三引号 保留空白

使用三引号的字符串可以跨越多行,而且可以将所有的空白字符都包含在该字符串中。如果有保持样式的需求,那么就需要使用三引号。

print('''\
===========字符串===========

三引号字符串会保留空白字符,
从而实现保持样式的效果
''')

运行效果如下:

图片描述


2.7 字符串方法

查看方法列表 dir函数

字符串对象有很多内建方法,我们通常会使用 dir() 函数查看。dir() 函数会列出该对象的属性和方法。

a = 'hello'
dir(a)

运行效果如下:

图片描述

查看帮助 help函数

当我们想知道某个方法的使用方法,我们会使用 help 函数查看。比如,我们想知道 upper 方法是如何使用的。

a = 'hello'
help(a.upper)

运行效果如下:

图片描述

帮助文档告诉我们,upper 方法会返回这个字符串的大写版本。帮助文档查看完毕,按 q 退出。

接下来,我们先测试刚刚查看的效果,然后再介绍几个常用的字符串方法,更多的方法的使用大家可以使用 help() 函数去查看。

upper() 方法返回大写的字符串

a = 'hello world!'
a.upper()

运行效果如下:

图片描述


lower() 返回小写的字符串

a = 'Hello World!'
a.lower()

运行效果如下:

图片描述


swapcase() 返回字符串大小写交换后的版本

a = 'Hello World!'
a.swapcase()

运行效果如下:

图片描述


replace(old,new) 对字符串中的子字符串进行替换

a = 'Hello World!'
a.replace('World','Lanqiao')

运行效果如下:

图片描述


strip() 方法默认会删除开头和结尾的空白字符:

a = ' Hello World !  '
a.strip()

运行效果如下:

图片描述

也可以指定开头和结尾的其他字符

a = '==============Hello World!=============='
a.strip('=')

图片描述


需要注意的是,strip() 方法只能删除开头和结尾的字符


split() 方法默认以空格作为分隔符对字符串进行拆分

split() 方法默认以空格作为分隔符对字符串进行拆分,连在一起的空格会被视为单个字符,分隔之后会以列表形式返回(我们会在后面章节介绍列表)。

a = 'Hello World      Hello World'
a.split()

运行效果如下:

图片描述

当然,也可以指定分隔符。

a = 'hello,world'
a.split(',')

运行效果如下:

图片描述


join() 方法可以使用指定字符串连接多个字符串。

a = 'Hello Wolrd'
'-'.join(a.split())

运行效果如下:

图片描述

以下实例展示了join()的使用方法:

- symbol = "-";
seq = ("a", "b", "c");# 字符串序列 
print symbol.join( seq );

以上实例输出结果如下:

a-b-c

find() 方法可以返回要查找的子字符串的最小索引

前面我们在运算符部分介绍了 in 运算符,它可以判断一个字符串是不是另一个字符串的子字符串,但有时候我们还需要知道子字符串的位置。

a = 'Hello World'
a.find('Wo')

运行效果如下:

图片描述

所以,字符 Wo 的索引从 6 开始。

当要查找的子字符不存在时将返回 -1。

a = 'Hello World'
a.find('Story')

运行效果如下:

图片描述


len() 函数

我们可以通过 Python 的内置函数 len() 获得字符串的长度。

a = "Hello"
len(a)

运行效果如下:

图片描述


3 元组

3.1 元祖的创建

使用一对圆括号来表示空元组: ()

a = ()
type(a)

运行效果如下:

图片描述

使用一个后缀的逗号来表示单元组: a, 或 (a,)

a = (5)    #当缺少逗号时
print(a)
type(a)
b = (5,)    #加上逗号之后
print(b)
type(b)

运行效果如下:

图片描述

单元组一定要加上逗号,否则不会被当成元组处理。

使用以逗号分隔的多个项: a, b, c or (a, b, c)

a = '中国','日本','朝鲜'
type(a)
b = ('中国','日本','朝鲜')
type(b)

图片描述

使用内置的 tuple()tuple(iterable)

terable 指可迭代对象,像字符串、元组、列表、字典、集合都是可迭代对象,但数字不是可迭代对象。

a = tuple()    #生成一个空元组
print(a)
type(a)
number = '123456789'
tuple(number)

运行效果如下:

图片描述

也就是把字符串number变为元祖类型。


3.2 元组的索引和切片

元组和字符串的一样,也可以使用下标索引来访问元组中的值:

t = ('a','b','c','d','e')
t[0]    #访问元素
t[4]    #访问元素
t[0:3]    #切片
t[::-1]    #翻转

运行效果如下:

图片描述


3.3 元组的修改

因为元组是不可变数据类型,当我们试图通过索引去修改元组的某个元素时,将会报错。

a = ('a','b','c','d','e')
a[0] = 'f'

运行效果如下:

图片描述

但我们有时候也会有修改数据的需求,这时候我们就可以结合 + 运算符和切片操作来实现。

a = ('a','b','c','d','e')
a = ('f',) + a[1:]
print(a)

运行效果如下:

图片描述

需要注意的是,虽然我们实现了元组的修改,但此时的元组对象已经发生了变化,所以我们本质上是新建了一个元组。


3.4 元组的运算符

与字符串一样,元组也有很多可以使用的运算符,比如 +*in等。

+ 运算符

a = (1,2,3)
b = ('3','4',5)
c = a + b
print(c)

运行效果如下:

图片描述

* 运算符

a = (1,3,5)
a * 3

运行效果如下:

图片描述

innot in 运算符

a = (1,3,5,7,9)
print(1 in a)
print('5' in a)    #注意元素的类型
print(3 not in a)

运行效果如下:

图片描述


3.5 元组解包

在我们创建元组时 a = 1,2,3元组打包 的例子,所以我们使用逆操作实现 元组解包

a = 1,2,3
print(a)
x,y,z = a
print(x)
print(y)
print(z)

运行效果如下:

图片描述


3.6 元组的常用函数和方法

count() 方法可以统计某个元素的的数量

a = (1,2,3,1,5,3,7,8,9)
a.count(1)

运行效果如下:

图片描述

len() 函数可以统计元素的个数

a = (1,2,3,4,5,6,7,8,9)
len(a)

运行效果如下:

图片描述

max() 函数可以返回元组中元素最大值。

a = (1,5,6,3,2)
max(a)

运行效果如下:

图片描述

min() 函数可以返回元组中元素最小值。

a = (1,5,6,3,2)
min(a)

运行效果如下:

图片描述


4 列表

4.1 列表定义和类型(可变)

列表(list)是方括号([])内用逗号分隔的一组值,列表可以包含不同类型的元素,但一般情况下,会在其中存储类型相同的元素。

列表是可变数据类型,我们可以做个实验来验证这一点。

a = [1,2,3]
print(a)
print(type(a),id(a))
a.append(4)    #新增元素
print(a)
print(type(a),id(a))

可以发现,通过列表的内置方法给列表新增了一个元素,但 id 值仍然保持不变。


4.2 列表的创建

使用一对方括号来表示空列表: []

a = []
print(a)
type(a)

运行效果如下:

图片描述

使用方括号,其中的项以逗号分隔: [a] 或 [a, b, c]

a = [1]
print(a)
type(a)
b = ['q','w','e','r']
print(b)
type(b)

运行效果如下:

图片描述

使用列表推导式: [x for x in iterable],iterable 是可迭代对象。

我们首先以元组作为可迭代对象

t = (1,2,3,4,5,6,7)
a = [i for i in t]
print(a)
type(a)

运行效果如下:

图片描述


再来用字符串作为可迭代对象。

n = 'abcdefg'
a = [i for i in n]
print(a)
type(a)

运行效果如下:

图片描述


使用类型的构造器: list() 或 list(iterable)

a = list()    #创建一个空列表,与 a = [] 一样
print(a)
type(a)
n = 'abcdefg'
b = list(n)    #将字符串转换为列表
print(b)
type(b)

运行效果如下:

图片描述


4.3 列表的索引和切片

和字符串、元组一样,列表也支持索引和切片。

s = [1, 2, 3, 4, 5, 6, 7, 8, 9]
s[0]    #获取索引 0 处的元素
s[-1]    #获取索引 -1 处的元素
s[2:5]    #切片
s[::-1]    #翻转列表
s[::2]    #步长为 2 生成新列表

运行效果如下:

图片描述


4.4 列表元素的添加

append() 方法可以在列表末尾追加元素

a = [1,2,3]
print(a)
a.append(4)        #末尾追加元素 4
print(a)

运行效果如下:

图片描述

extend() 方法可以通过可迭代对象将多个元素到列表中

a = [1,2,3,4,5]
print(a)
a.extend('abcde')        #把字符串的每个字符添加到列表中
print(a)
a.extend([6,7,8,9,10])    #通过列表添加多个元素到列表 a
print(a)

运行效果如下:

图片描述


insert() 方法可以按照索引插入元素

t = ['a','c','d','e']
print(t)
t.insert(1,'b')    #在索引 1 的位置插入元素 'b'
print(t)

运行效果如下:

图片描述


4.5 列表元素的删除

pop删除指定索引元素

pop() 方法是列表的内置方法,有个可选参数索引( index )默认是 -1,也就是说默认删除最后一个元素,我们也可以设定需要删除的元素索引。

pop() 方法在删除元素后会返回删除的元素。

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(letters)
letters.pop()        #默认删除最后一个元素
print(letters)
letters.pop(3)        #指定索引,索引从0开始,也就是删除第 4 个元素

运行效果如下:

图片描述


remove() 根据元素值删除

remove() 方法是根据元素的值进行删除,所以必须指定要删除的元素。remove() 方法删除之后不会返回删除的元素,这一点与 pop() 方法不同。

a = [1, 2, 3, 4, '5', 6, 7, '8', 9]
print(a)
a.remove(2)        #删除元素 2
print(a)
a.remove('8')        #删除元素 '8'
print(a)

运行效果如下:

图片描述


clear() 方法会清空列表

a = [1, 2, 3, 4, '5', 6, 7, '8', 9]
a.clear()
a

运行效果如下:

图片描述


del 语句 根据索引删除但不返回值

del 语句和 pop() 方法一样,也是使用索引进行删除元素,不过 del 语句不会返回删除的元素。 del 语句还可以删除切片甚至删除整个列表,这一点 pop() 方法就不支持。

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(a)
del a[-1]    #删除最后一个元素
print(a)
del a[2:5]        #删除切片[2:5]
print(a)
del a[:]        #删除列表中全部元素
print(a)
del a            #删除列表
print(a)

运行效果如下:

图片描述


4.6 列表的修改

列表元素的修改

列表可以通过索引或切片赋值改变列表元素,甚至清空整个列表。

letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(letters)
letters[0] = 'A'            #通过索引将第一个元素修改为 'A'
print(letters)
letters[2:5] = ['C', 'D', 'E']    #通过切片对第 345 个元素进行修改
print(letters)
letters[5:] = []            #将第 6 个之后的元素清空
print(letters)
letters[:] = []            #将整个列表清空
print(letters)

运行效果如下:

图片描述


4.7 列表排序

  • 内置方法 sort 可以实现对列表的排序。
ord() 函数是 chr() 函数(对于 8 位的 ASCII 字符串)的配对函数
它以一个字符串(Unicode 字符)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值。
letters = ['a','aa','B','cc','b','A','bb','c']
letters.sort()        #默认按照 Unicode 数值排序,数值越小越靠前
letters
ord('A')  # 65
ord('B')   # 66
ord('a')   # 97
ord('b')  # 98

图片.png


  • 可选参数 reverse 默认 Flase ,如果设置为 True 就是反向排序。
letters = ['a','aa','B','cc','b','A','bb','c']
letters.sort(reverse=True)
letters

运行效果如下:

图片描述


  • 另外还有一个可选参数 key 可以实现更复杂的排序。
letters = ['a','aa','B','cc','b','A','bb','c']
letters.sort(key=str.upper)        #按照大写字母的形式排序
letters
letters.sort(key=str.lower)        #按照小写字母的形式排序
letters
letters.sort(key=len)        #按照元素的长度排序,元素必须是可迭代对象
letters

运行效果如下:

图片描述


reverse() 方法可以实现对列表 x 的翻转,与切片 x[::-1] 类似,不过切片不会修改原列表,所以更推荐使用切片。

letters = ['a','aa','B','cc','b','A','bb','c']
print(letters)
letters[::-1]    #翻转之后的结果,如果有需要,可以赋值给其他变量
print(letters)        #原列表没有改变
letters.reverse()
print(letters)        #原列表已改变

图片.png

所以reverse() 方法翻转改变了列表,还是切片好,不会改变原来的列表。


4.8 列表的查询

通过内置方法 count() 查看元素出现的次数

fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
fruits.count('apple')
fruits.count('tangerine')

运行效果如下:

图片描述


index() 返回列表中第一个值为 x 的元素的索引值。

通过内置方法 index() 返回列表中第一个值为 x 的元素的索引值。未找到指定元素时,触发 ValueError 异常。

可选参数 start 和 end 是切片符号,用于将搜索限制为列表的特定子序列。但返回的索引仍然是基于整个序列计算的。

fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
fruits.index('banana')
fruits.index('banana', 4)        #从第 5 个元素开始寻找

运行效果如下:

图片描述


4.9 嵌套列表

嵌套列表就是在列表中包含列表。跟索引一样从0开始,比如下面是0,1,2

a = [[1,2,3],[4,5,6],[7,8,9]]
a[0]
a[1]
a[0][0]
a[2][1]

运行效果如下:

图片描述


4.10 列表的运算符

列表和字符串、元组一样,也是支持很多运算符。

print([1,2,3] + [4,5])    # + 运算符实现列表合并
print([1,2,3] * 3)        # * 运算符实现重复
print(3 in [1,2,3])        # in 运算符判断字符是否在列表中
print(3 not in [1,2,3])    # not in 运算符    

运行效果如下:

图片描述


5. 集合

集合(set)是一个 无序的不重复元素序列。满足数学上集合的三大属性 确定性互异性无序性 。常见的用途包括成员检测、从序列中去除重复项以及数学中的集合类计算,例如交集、并集、差集与对称差集等等。

前面我们提到过,集合是 可变数据类型,我们再来验证一下:

letters = {'a','b','c'}
print(letters)
print(type(letters),id(letters))
letters.add('d')        #增加一个元素 'd'
print(letters)
print(type(letters),id(letters))

运行效果如下:

图片描述

可以看到,我们通过内置方法给集合新增了一个元素,但内存地址没有发生改变,证明了集合是可变数据类型。


5.1 集合的创建

使用花括号内以逗号分隔元素的方式

a = {'jack', 'sjoerd'}
print(a)
type(a)

运行效果如下:

图片描述


使用集合推导式

a = {c for c in 'abracadabra'}    #集合在创建时会自动去掉重复元素
print(a)
type(a)

运行效果如下:

图片描述


使用类型构造器 set() 创建集合

a = set()        #可以创建空集合,不能用 {} 创建。
print(a)
type(a)
b = {}        #这样创建的是字典,我们下一节会讲
type(b)
c = set('foobar')    #通过可迭代对象创建集合,会自动去重
print(c)
type(c)

运行效果如下:

图片描述


5.2 集合添加元素

使用 add() 方法新增元素

letters = {'a','b','c'}
print(letters)
letters.add('d')    #新增一个元素 'd'
print(letters)

运行效果如下:

图片描述

使用 update() 方法可以将可迭代对象中的元素添加到集合中

letters = {'a','b','c'}
print(letters)
letters.update('defg')        #从字符串中添加
letters
letters.update(['x','y','z'])    #从列表中添加
letters

运行效果如下:

图片描述


集合的无序性—添加元素顺序随机

因为集合的无序性,我们可以发现,添加的元素顺序非常随机。


5.3 集合删除元素

因为集合的无序性,所以它不存在切片索引的功能,此处我们将演示几种删除元素的方法。

remove() 方法会删除指定的元素,如果元素不存在就会报错。

letters = {'a','b','c'}
letters.remove('a')        #删除元素 'a'
letters
letters.remove('d')        #元素不存在会报错

运行效果如下:

图片描述


discard() 方法和 remove() 方法类似,不过当遇到不存在的元素时不会报错。

letters = {'a','b','c'}
letters.discard('a')        #删除元素 'a'
letters
letters.discard('d')        #元素不存在不会报错
letters

运行效果如下:

图片描述


pop() 方法会随机删除元素。

letters = {'a','b','c','d','e','f'}
letters
letters.pop()        #随机删除元素
letters
letters.pop()        #随机删除元素
letters

运行效果如下:

图片描述


clear() 方法会清空全部元素

letters = {'a','b','c','d','e','f'}
letters
letters.clear()        #清空元素
letters

运行效果如下:

图片描述


del 语句可以删除整个集合

前面我们使用 del 语句可以通过索引切片删除列表的元素,但因为集合的无序性,所以不存在索引切片的概念。但我们依然可以用 del 删除整个集合。

letters = {'a','b','c','d','e','f'}
del letters
letters

运行效果如下:

图片描述

可以看到,删除之后就无法再访问了。


5.4 交集

交集是两个集合的公有部分。

intersection 方法

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
a.intersection(b)
b.intersection(a)

运行效果如下:

图片描述

& 运算符

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
a & b
b & a

运行效果如下:

图片描述


5.5 并集

并集是合并两个集合。

union() 方法

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
a.union(b)
b.union(a)

运行效果如下:

图片描述

| 运算符

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
a | b
b | a

运行效果如下:

图片描述

需要注意的是,求并集使用 | 运算符,不能使用 +


5.6 差集

两个集合 A 和 B,所有属于 A 且不属于 B 的元素构成的集合,称为 A 与 B 的差集(A - B)。

根据概念,我们知道两个求差集是有先后顺序的,A 与 B 的差集B 与 A 的差集 就属于两回事。

difference() 方法

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
print(a.difference(b))    #a 与 b 的差集
print(b.difference(a))    #b 与 a 的差集

运行效果如下:

图片描述

- 运算符

a = {'a', 'r', 'b', 'c', 'd'}
b = {'a', 'l', 'c', 'm', 'z'}
print(a - b)    #a 与 b 的差集
print(b - a)    #b 与 a 的差集

运行效果如下:

图片描述


5.7 列表去重

我们知道,集合具有互异性,通俗来说就是唯一性,不会出现重复的元素,所以我们就可以使用集合给列表去重。

a = [1,2,3,2,5,3,2,1]
b = set(a)    #将列表转换为集合
c = list(b)    #将集合转换回列表
print(c)

运行效果如下:

图片描述


总结

本节我们介绍了集合增删元素和数学上交并差在 Python 的实现,最后还提到集合可以给列表去重,需要注意的是,集合和字符串、元组、列表相比,集合具有无序性,所以没有索引和切片。


6 字典

前面我们学习过的字符串、元组、列表都是使用从 0 开始的整数作为索引,而字典键(key)为索引,键通常是字符串或数字,也可以是其他任意不可变类型

字典中每一个 元素 都是一个 key 和一个 value 的组合。我们可以把字典理解为 键值对 的集合,字典的键必须是唯一的。


从 Python 3.6 开始,dict 对象会保持插入时的顺序,在 Python 3.7 中正式宣布该特性成为 Python 语言官方规范的一部分。我们环境目前使用的是 Python 3.8 版本,自然也是支持该特性的。

字典是 可变数据类型,我们仍像之前一样,进行验证。

age = {'James':23, 'Leonard':25, 'Antetokounmpo':32, 'Durant':24}    #这是一个字典
print(age)
print(type(age),id(age))
age['Harden'] = 19    #字典增加元素
print(age)
print(type(age),id(age))

运行效果如下:

图片描述


6.1 字典的创建

在花括号({})内以逗号分隔 键:值 对的方式

a = {}        #空字典的创建
print(a)
type(a)
b = {'jack': 4098, 'sjoerd': 4127}
print(b)
type(b)

运行效果如下:

图片描述


使用字典推导式

a = {x: x ** 2 for x in range(10)}
print(a)
type(a)

运行效果如下:

图片描述


使用类型构造器 dict() 创建字典

下面的例子中,a 是使用 {} 创建的字典,其他都是通过 dict() 构造函数创建的。其中 s 创建了一个空字典,b 直接用关键字参数指定键值对。

s = dict()        #空字典
print(s)
type(s)
a = {'one': 1, 'two': 2, 'three': 3}
b = dict(one=1, two=2, three=3)
c = dict([('two', 2), ('one', 1), ('three', 3)])
d = dict({'three': 3, 'one': 1, 'two': 2})
e = dict({'one': 1, 'three': 3}, two=2)
print(a == b == c == d == e)        # a、b、c、d、e 都一样
print(b)
type(b)

运行效果如下:

图片描述


6.2 字典的查询

我们可以通过 d[key] 的方式查询字典 d 中以 key 为键的项的值。

a = {'one': 1, 'two': 2, 'three': 3}
a['one']
a['two']

运行效果如下:

图片描述

正常情况下,当我们要查询的键(key)存在于字典中的时候,上面的查询方式没有问题。但当不存在时,就会抛出 KeyError 异常。

a = {'one': 1, 'two': 2, 'three': 3}
a['four']    #不存在会抛出异常

运行效果如下:

图片描述


基于上面的原因,我们更推荐使用字典的内置方法 get(),该方法在查询时遇到不存在的 key 不会报错,而是会默认返回 None,我们也可以自行定制返回值。

a = {'one': 1, 'two': 2, 'three': 3}
a.get('four')    #key 不存在不会报错
a.get('four','这个值不存在')    #自定义 key 不存在时的返回值

运行效果如下:

图片描述


6.3 字典元素的增加和修改

在字典中 增加元素修改元素 的代码其实是相同的,只需要为字典中某一个 key 进行赋值,区别在于:

  • 如果此时 key 存在,则判断为你在修改元素,更新该 key 对应的 value
  • 如果不存在,则判断为你在添加元素,向字典中增加该 key: value 键值对,从 Python 3.6 开始,Python 会保持元素插入顺序,新的元素会在字典末尾。
a = {'one': 1, 'two': 2, 'three': 3}
a['one'] = '一'        #修改元素
print(a)
a['four'] = 4        #添加元素到末尾
print(a)

运行效果如下:

图片描述


6.4 字典的删除

pop(key[, default]) 方法

pop(key[, default]) 方法在 key 存在于字典时会删除并返回对应的值(value);key 不存在时返回 default,没有设置 default 会发生 KeyError 异常。

a = {'one': 1, 'two': 2, 'three': 3}
a.pop('one')                #删除会返回 'one' 对应的值
print(a)
a.pop('four','您在删除不存在的内容')    #设置 default
a.pop('four')                #未设置 default,当删除不存在的 key 时会报错

运行效果如下:

图片描述


popitem() 方法

popitem() 方法会从字典中删除并返回一个 (键, 值) 元组。因为从 Python 3.6 开始,dict 对象会保持插入时的顺序,所以该方法保持 后进先出 的删除顺序,当字典为空时会发生 KeyError 异常。

a = {'one': 1, 'two': 2, 'three': 3}
a.popitem()
a.popitem()
a.popitem()
print(a)        #此时字典已空
a.popitem()        #空字典继续删除会报错

运行效果如下:

图片描述


del 语句需要指定 字典名 和需要删除的 key 值,key 不存在时发生 KeyError 异常。

a = {'one': 1, 'two': 2, 'three': 3}
del a['one']
print(a)
del a['four']    #删除不存在的内容

运行效果如下:

图片描述


clear() 清空字典

a = {'one': 1, 'two': 2, 'three': 3}
a.clear()
print(a)

运行效果如下:

图片描述


6.5 字典视图对象

a.keys()        #由字典的键(key)组成
a.values()        #由字典的值(value)组成
a.items()        #由字典项 ((键, 值) 对) 组成

运行效果如下:

图片描述


因为字典视图对象是可迭代的,所以可以通过 list()set()tuple() 等构造函数将其转换成对应的类型,然后就可以进行切片索引之类的操作。

a = {'one': 1, 'two': 2, 'three': 3}
b = a.keys()
list(b)        #转换成列表
set(b)        #转换成集合
tuple(b)    #转换成元组

运行效果如下:

图片描述


7 本章总结:

在 Python 中,数据类型分为不可变数据类型可变数据类型


  • 不可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址也会发生改变,对于这种数据类型,就称不可变数据类型。数字字符串元组 属于不可变数据类型。
  1. 数字

    • 数字类型分为整数类型(int)、浮点数类型(float)、复数类型(complex)
    • 布尔类型(bool)是整型的子类型,由两个常量对象 True 和 False 组成,它们用来表示逻辑上的真和假。
    • 浮点数类型是使用 C 语言的 double 类型来实现,可以近似表示数学中的实数。
    • decimal 模块可以实现快速正确的十进制浮点数计算。
    • 复数由实数部分和虚数部分构成,可以用 a + bj,或者 complex(a,b) 表示,复数的实部 a 和虚部 b 都是浮点型。
    • Python 支持非常丰富的数学运算。
  2. 字符串

    • 字符串是 Python 中最常用的数据类型。我们一般使用单引号('...') 或双引号( "..." )来创建字符串。我们也可以使用 str() 创建一个空字符串。
    • 字符串、元组、列表、集合都支持从 0 开始的数字索引。
    • 字符串切片的语法: string[start:end:step]
    • f-string 是 Python 在 Python 3.6 引入的格式化方案,是在普通字符串前面加上 fF,然后在字符串中使用大括号( {})引入变量或表达式。另外还有 format() 格式化和 % 格式化。
    • 三引号的字符串可以跨越多行,而且可以将所有的空白字符都包含在该字符串中。如果有保持样式的需求,那么就需要使用三引号。
    • 字符串支持 + 连接运算符、* 重复运算符等。
  3. 元组

    • 元组(tuple)由多个用逗号隔开的值组成,支持索引和切片。
    • 元组支持 + 连接运算符、* 重复运算符等。
    • 创建元组时,a = 1,2,3元组打包,我们使用逆操作实现 元组解包
    • len() 函数可以统计元组中元素的个数
    • max() 函数可以返回元组中元素最大值。
    • min() 函数可以返回元组中元素最小值。
  • 可变数据类型:当该数据类型的对应变量的值发生了改变,那么它对应的内存地址不发生改变,对于这种数据类型,就称可变数据类型。列表集合字典属于可变数据类型。
  1. 列表

    • 列表(list)是方括号([])内用逗号分隔的一组值,列表可以包含不同类型的元素。
    • 和字符串、元组一样,列表也支持索引和切片,支持多个运算符操作。
    • 添加元素的方法有:append()extend()insert()
    • 删除元素的方法有:pop()remove()clear() 以及 del 语句
    • 列表可以通过索引或切片赋值从而改变列表元素
  2. 集合

    • 集合(set)是一个无序的不重复元素序列,满足数学上集合的三大特性 确定性互异性无序性
    • 因为集合的 无序性 ,所以集合不支持索引和切片。
    • 集合添加元素可以通过 add() 方法和 update() 方法
    • 集合删除元素可以通过 remove() 方法、 discard 方法、pop() 方法、clear() 方法以及 del 语句
    • 集合支持数学上的交集(&)、差集(-)、并集(|)等运算。
    • 可以通过将其他数据类型先转换成集合,然后再转换回去,实现去重操作。
  3. 字典

    • 字典(dict) 是一种常用的 Python 內置数据类型。字符串、元组、列表都是使用从 0 开始的整数作为索引,而字典以键(key)为索引,键通常是字符串或数字,也可以是其他任意不可变类型。字典中每一个 元素 都是一个 key 和一个 value 的组合。我们可以把字典理解为 键值对 的集合,字典的键必须是唯一的。
    • 从 Python 3.6 开始,dict 对象会保持插入时的顺序,在 Python 3.7 中正式宣布该特性成为 Python 语言官方规范的一部分。
    • 我们可以通过 d[key] 的方式查询字典 d 中以 key 为键的项的值,但 key 不存在时会报错,更推荐使用字典的内置方法 get()
    • 在字典中 增加元素修改元素 的代码其实是相同的,只需要为字典中某一个 key 进行赋值。key 存在,就是更新该 key 对应的 value 值;key 如果不存在,则会添加该元素。
    • pop(key[, default]) 方法在 key 存在于字典时会删除并返回对应的值(value);key 不存在时返回 default,没有设置 default 会发生 KeyError 异常。
    • popitem() 方法会从字典中删除并返回一个 (键, 值) 元组。因为从 Python 3.6 开始,dict 对象会保持插入时的顺序,所以该方法保持 后进先出 的删除顺序,当字典为空时会发生 KeyError 异常。
    • dict.keys(), dict.values()dict.items() 所返回的对象称为视图对象。 该对象提供字典条目的一个动态视图,当字典改变时,视图也会相应改变。