Python 零基础入门教程第 3 章. 基本数据类型 (二)

一、序列类型

序列类型用来表示有序的元素集合。

1. 字符串

python 中字符串用 str 表示,字符串是使用单引号,双引号,三引号包裹起来的字符的序列,用来表示文本信息。

1.1 字符串的定义

a = 'a'
b = "bc"
c = """hello,world"""
d = '''hello,d'''
e = """
    hello,
    world!
    """
print('a的类型为:', type(a))    # a的类型为: <class 'str'>
print('b的类型为:', type(b))    # b的类型为: <class 'str'>
print('c的类型为:', type(c))    # c的类型为: <class 'str'>
print('d的类型为:', type(d))    # d的类型为: <class 'str'>
print('e的类型为:', type(e))    # e的类型为: <class 'str'>

a 的类型为: <class 'str'>
b 的类型为: <class 'str'>
c 的类型为: <class 'str'>
d 的类型为: <class 'str'>
e 的类型为: <class 'str'>
使用单引号和双引号进行字符串定义没有任何区别,当要表示字符串的单引号时用双引号进行定义字符串,反之亦然。

一对单引号或双引号只能创建单行字符串,三引号可以创建多行表示的字符串。三双引号一般用来做多行注释,表示函数,类定义时的说明。

print('最近我看了"平凡的世界"')
print("最近我看了'平凡的世界'")

最近我看了"平凡的世界"
最近我看了'平凡的世界'

定义空字符串
a = ''
print(a)

1.2 字符串的索引

任何序列类型中的元素都有 索引 用来表示它在序列中的位置。

字符串是字符的序列表示,单个字符在字符串中的位置使用 索引 来表示,也叫下标。

索引使用整数来表示。
image.png

通过 索引 可以获取字符串中的单个字符

语法如下:

str[index]
s = 'hello world!'
print(s[0])
print(s[-1])

h
!
注意字符串索引从 0 开始

1.3 字符串的切片

获取序列中的子序列叫切片。

字符串的切片就是获取字符串的子串。

字符串切片的语法如下:

str[start:end:step]

start 表示起始索引,end 表示结束索引,step 表示步长。

str[m:n:t] 表示从字符串索引为 mn 之间不包含 n 每隔 t 个字符进行切片。

step 为 1 的时候可以省略。

特别的,当 step 为负数时,表示反向切片。

s = '0123456789'
print(s[1:5])  # 包头不包尾

1234

print(s[:5])  # 从头开始切可以省略start

01234

print(s[1:])  # 切到末尾省略end

123456789

print(s[1::2]) # 步长为2进行切片

13579

print(s[1::-2]) # 步长为负数反向切片

1

思考

获取一个字符串的逆串,例如 'abc' 的逆串是 'cba'

1.4 字符串拼接

python 中可以通过 + 拼接两个字符串

a = 'hello'
b = ' '
c = 'world!'
print(a+b+c)

hello world!
字符串和整数进行乘法运算表示重复拼接这个字符串

print('*' * 10)

1.5 字符串常用方法

通过内建函数 dir 可以返回传入其中的对象的所有方法名列表。

print(dir(str))

['add', 'class', 'contains', 'delattr', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getitem', 'getnewargs', 'gt', 'hash', 'init', 'init_subclass', 'iter', 'le', 'len', 'lt', 'mod', 'mul', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'rmod', 'rmul', 'setattr', 'sizeof', 'str', 'subclasshook', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
通过内建函数 help 可以返回传入函数的帮助信息。

help('abc'.replace)

Help on built-in function replace:

replace(old, new, count=-1, /) method of builtins.str instance
Return a copy with all occurrences of substring old replaced by new.

count
Maximum number of occurrences to replace.
-1 (the default value) means replace all occurrences.

If the optional argument count is given, only the first count occurrences are
replaced.
官方文档地址

1.6 字符串和数值的相互转化

1'1' 不同,1.2'1.2' 也不相同,但是它们可以相互转化

# 整数和字符串之间的转化
int('1')

1

str(1)

'1'

# 浮点数和字符串之间的转化
float('1.2')

1.2

str(1.2)

'1.2'

# 尝试 int('1.2')看看结果会是什么
int('1.2')

1.7 转义符

在需要在字符中使用特殊字符时,python 用反斜杠 \ 转义字符。常用转义字符如下表:

(在行尾时) 续行符
\\ 反斜杠符号
\' 单引号
\" 双引号
\a 响铃
\n 换行
\t 横向制表符
\r 回车
\f 换页
print('窗前明月光,\n疑是地上霜。')  # 输出换行

窗前明月光,
疑是地上霜。

print('对\\错')   # 输出反斜杠本身

对\错

print('\'')      # 输出单引号本身

'

1.8 字符串格式化

在实际工作中经常需要动态输出字符。

例如,我们通过程序计算计算机的内存利用率,然后输出

10:15 计算机的内存利用率为30%

其中下划线内容会动态调整,需要根据程序执行结果进行填充,最终形成上述格式的字符串输出。

python 支持两种形式的字符串格式化

% 字符串格式化

语法格式如下:

%[(name)][flags][width][.precision]typecode
res = '%s计算机的内存利用率为%s%%' % ('11:15', 75)
print(res)
# '%s'作为槽位和 % 号后提供的值按顺序一一对应

11:15 计算机的内存利用率为 75%

res = '%(time)s计算机的内存利用率为%(percent)s%%' % {'time':'11:15', 'percent': 75}
# % 后是字典时,可以通过name指定key对应的值
print(res)

11:15 计算机的内存利用率为 75%

# 输出两位数的月份,例如01,02
res = '%02d' % 8
print(res)

08

# 保留2为小数
res = '%(time)s计算机的内存利用率为%(percent).2f%%' % {'time':'11:15', 'percent': 75.123}
print(res)

11:15 计算机的内存利用率为 75.12%

print('字符串%(key)s,十进制%(key)d,科学计数%(key)e,八进制%(key)o,16进制%(key)x,unicode字符%(key)c' % {'key': 65})

字符串 65,十进制 65,科学计数 6.500000e+01,八进制 101,16 进制 41,unicode 字符 A

format 函数格式化

% 的字符串格式化继承自 C 语言,python 中给字符串对象提供了一个 format 函数进行字符串格式化,且功能更强大,并且大力推荐,所以我们要首选使用。

基本语法是:

<模板字符串>.format(<逗号分隔的参数>)

在模板字符串中使用 {} 代替以前的 % 作为槽位

'{}计算机的内存利用率为{}%'.format('11:15', 75)

'11:15 计算机的内存利用率为 75%'
当 format 中的参数使用位置参数提供时,{} 中可以填写参数的整数索引和参数一一对应

'{0}计算机的内存利用率为{1}%'.format('11:15', 75)

'11:15 计算机的内存利用率为 75%'
当 format 中的参数使用关键字参数提供时,{}中可以填写参数名和参数一一对应

'{time}计算机的内存利用率为{percent}%'.format(time='11:15', percent=75)

'11:15 计算机的内存利用率为 75%'
{} 中除了可以写参数索引外,还可以填写控制信息来实现更多的格式化功能,语法如下

{<参数序号>:<格式控制标记>}
其中格式控制标记格式如下
[fill][align][sign][#][0][width][,][.precision][type]
# 输出两位数的月份,例如01,02
res = '{:0>2}'.format(8) 
print(res)

08

# 保留2为小数
res = '{time}计算机的内存利用率为{percent:.2%}'.format(time='11:15', percent=0.75123)
print(res)

11:15 计算机的内存利用率为 75.12%

print('字符串{key},十进制{key:d},科学计数{key:e},八进制{key:o},16进制{key:x},unicode字符{key:c}'.format(key=65))

字符串 65,十进制 65,科学计数 6.500000e+01,八进制 101,16 进制 41,unicode 字符 A

2. 列表

python 中列表(list)用来表示有序可变元素的集合,元素可以是任意数据类型。

2.1 列表的定义

列表由一对中括号进行定义,元素与元素直接使用逗号隔开。

a = []                      # 空列表
b = ["a", "b", "cde"]       # 字符串列表项
c = [1, "b", "c"]           # 数字列表项  
d = [1, "b", []]            # 列表列表项
e = [1, "b", [2, "c"]]      # 列表作为列表的元素叫做列表的嵌套


print('a的类型为:', type(a))    # a的类型为: <class 'list'>
print('b的类型为:', type(b))    # b的类型为: <class 'list'>
print('c的类型为:', type(c))    # c的类型为: <class 'list'>
print('d的类型为:', type(d))    # d的类型为: <class 'list'>
print('e的类型为:', type(e))    # e的类型为: <class 'list'>

a 的类型为: <class 'list'>
b 的类型为: <class 'list'>
c 的类型为: <class 'list'>
d 的类型为: <class 'list'>
e 的类型为: <class 'list'>

2.2 列表的拼接

像字符串一样,列表之间可以进行加法运算实现列表的拼接,列表可以和整数进行乘法运算实现列表的重复。

[1,2,3] +  [4,5,6]

[1, 2, 3, 4, 5, 6]

[1,2,3] * 3

[1, 2, 3, 1, 2, 3, 1, 2, 3]

2.3 列表的索引和切片

序列的切片操作完全一致,参见字符串

注意嵌套列表的元素获取

ls = [1,2,['a','b']]
ls[2][0]

'a'

2.4 列表的常用操作

python 中的列表操作非常灵活,是非常重要和经常使用的数据类型。

2.4.1 修改元素

列表的中的元素可以进行修改,只需使用索引赋值即可。

ls = [1,2,3]
ls[1] = 'a'
print(ls)

[1, 'a', 3]

2.4.2 增加元素

给列表添加元素需要使用到列表的方法

.append(el),在列表的末尾添加一个元素

ls = [1,2,3]
ls.append(4)
print(ls)

[1, 2, 3, 4]
.insert(index, el),在列表的指定索引处插入一个元素

ls = [1,2,3]
ls.insert(0,0)
print(ls)

[0, 1, 2, 3]
.extend(iterable),扩展列表,元素为传入的可迭代对象中的元素

ls = [1,2,3]
ls.extend([4,5,6])
print(ls)

[1, 2, 3, 4, 5, 6]

2.4.3 删除元素

.pop(index=-1),删除指定索引的元素,并返回该元素,没有指定索引默认删除最后一个元素

ls = [1,2,3]
ls.pop()

3

print(ls)

[1, 2]

ls.pop(0)

1

print(ls)

[2]
.remove(value),从列表中删除第一个指定的值 value,如不不存在 value 则报错。

ls = [1,2,3,1]
ls.remove(1)
print(ls)

[2, 3, 1]
.clear(),清空列表,原列表变成空列表

ls = [1,2,3]
ls.clear()
print(ls)

[]

2.5 列表的其他方法

.copy() 返回一个列表的浅拷贝。在讲可变与不可变类型的时候再详细讨论。

.count(value),统计列表中 value 的出现次数

ls = [1,2,3,1]
ls.count(1)

2
.index(self, value, start=0, stop=9223372036854775807),返回列表中指定值 value 的第一个索引,不存在则报错

ls = [1,2,3,1]
ls.index(1)

0

l.index(1,1)

3
.reverse(),翻转列表元素顺序

ls = [1,2,3]
ls.reverse()
print(ls)

[3, 2, 1]
.sort(key=None, reverse=False),对列表进行排序,默认按照从小到大的顺序,当参数 reverse=True 时,从大到小。注意列表中的元素类型需要相同,否则抛出异常。

ls = [2,1,3]
ls.sort()
print(ls)

[1, 2, 3]

# 从大到小
ls.sort(reverse=True) 
print(ls)

[3, 2, 1]

ls = [1,2,'3']
ls.sort()

TypeError Traceback (most recent call last)

in
1 ls = [1,2,'3']
----> 2 ls.sort()

TypeError: '<' not supported between instances of 'str' and 'int'

2.6 字符串和列表的转换

字符串是字符组成的序列,可以通过 list 函数将字符串转换成单个字符的列表。

s = 'hello world!'
ls = list(s)
print(ls)

['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']
由字符组成的列表可以通过字符串的 join 方法进行拼接

# 接上面的案例
''.join(ls)

'hello world!'

3. 元组

元组(tuple)表示有序不可变元组的集合,元素可以是任意数据类型,可以说元组就是不可变的列表。

3.1 元组的定义

元组通过一对小括号进行定义,元组之间使用逗号隔开。

a = ()                      # 空元祖
b = ("a", "b", "cde")       # 字符串
c = (1, "b", "c")           # 数字
d = (1, "b", [])            # 列表
e = (1, "b", (2, "c"))      # 元祖
f = 1,2

print('a的类型为:', type(a))    # a的类型为: <class 'tuple'>
print('b的类型为:', type(b))    # b的类型为: <class 'tuple'>
print('c的类型为:', type(c))    # c的类型为: <class 'tuple'>
print('d的类型为:', type(d))    # d的类型为: <class 'tuple'>
print('e的类型为:', type(e))    # e的类型为: <class 'tuple'>
print('f的类型为:', type(f))    # f的类型为: <class 'tuple'>

a 的类型为: <class 'tuple'>
b 的类型为: <class 'tuple'>
c 的类型为: <class 'tuple'>
d 的类型为: <class 'tuple'>
e 的类型为: <class 'tuple'>
f 的类型为: <class 'tuple'>
注意单元素元组的定义,一定要多加个逗号

g = ('hello')
h = ('hello',)
print('g的类型为:', type(g))    # g的类型为: <class 'str'>
print('h的类型为:', type(h))    # h的类型为: <class 'tuple'>

g 的类型为: <class 'str'>
h 的类型为: <class 'tuple'>

3.2 元组的索引和切片

序列的索引和切片完全一致,参加字符串。

3.2 元组的常用操作

元组的元素不能修改,增加和删除,其他操作和列表的操作一致。

元组利用不可修改的特性,应用在多变量赋值和函数多返回值上。

a, b = (1, 2)
# 经常简写为a, b= 1, 2

当然多变量赋值时可以使用可迭代对象,但是元组最安全,它是不可变的。

关于函数多返回值的问题我们后面再讲

3.3 元组的常用方法

元组只有两个公有方法 count,index 用法与列表相同。

3.4 len 函数

python 内建函数 len 可以获取对象中包含的元素个数

s = 'hello'
ls = [1,2,3]
t = (1,2,3)
print(len(s))
print(len(ls))
print(len(t))

5
3
3

4. 可变类型与不可变类型

python 中的数据类型根据底层内存机制分为可变和不可变两种。

基本数据类型中可变类型有列表,集合和字典,其他为不可变类型。直观的体现为,不可变类型数据创建后不能修改,只能重新创建。

通过内建函数 hash 可以对数据进行运算,凡是不可 hash 的都是可变类型,可以 hash 的是不可变类型

hash(1)

1

hash([1,2])

TypeError Traceback (most recent call last)

in
----> 1 hash([1,2])

TypeError: unhashable type: 'list'

5.赋值与深浅拷贝

5.1 赋值

python 是解释型编程语言,当解释器在碰到赋值语句时它首先会计算赋值符号右边的表达式的值,然后再创建左边的变量。

变量中实际存储的是值在内存中的地址,引用变量时通过地址指向内存中的值。通过内建函数 id 可以查看解释器中变量的虚拟内存地址整数值。

a = 1
id(a)

4382612480
将一个变量赋值给另外一个变量时,并不会创建新的值,只是新变量会指向值的内存地址

a = 1
b = a
id(a) == id(b)

True
对于字符串和数字这样的不可变数据类型,当上例中的变量 a 自加 1 时,会创建一个新值重新,它不会改变原来的值。因此对变量 b 没有影响。

a += 1
print(a)
print(b)

2
1
但是看下面的案例

ls = [1,2,3]
ln = ls
ls[0] = 2
print(ls)

[2, 2, 3]
会发现变量 ls 在修改列表的值后,变量 ln 的值也发生了同样的改变,这是因为 ls,ln 指向相同的列表。对可变数据类型进行变量赋值时要考虑这个特性。

5.2 浅拷贝

导入 copy 模块中的 copy 函数就是浅拷贝操作

import copy
a = 123
s = 'hello'
b = copy.copy(a)
d = copy.copy(s)
print(id(a),id(b))
print(id(s),id(d))

4382616384 4382616384
140571355341296 140571355341296
对于字符串数字这种不可变数据类型来说,浅拷贝相当于变量赋值,所以变量 a 和 b 的 id 相等,变量 s 和 d 的 id 相等。

a += 1
print(a)
print(b)

124
123
对原变量的修改会创建新的值,不会影响浅拷贝生成的变量,变量 a 自加 1 后指向值 124,变量 b 的值不变

对于可变数据类型,列表,字典,集合等浅拷贝会有不一样的结果。

ls = [1,'2',['a','b']]
ln = copy.copy(ls)
print(id(ls),id(ln))

140571352915648 140571355343040
当对可变数据类型进行浅拷贝时,会创建一个新的数据,所以变量 ls 和 ln 的 id 不想等。

print(id(ls[2]),id(ln[2]))

140571355288384 140571355288384
但只会拷贝第一层,ls 列表中的元素,ln 中只是引用,ln 中的每个对应位置指向的内存地址和 ls 相同。

ls[0] = 2
print(ls)
print(ln)

[2, '2', ['a', 'b']]
[1, '2', ['a', 'b']]
修改 ls 中第一个元素,因为是不可变数据类型,所以 ls 中第一个位置指向了新的内存地址,ln 中的不变。

ls[2][0] = 1
print(ls)
print(ln)

[2, '2', [1, 'b']]
[1, '2', [1, 'b']]
修改 ls 中最后一个元素,因为是可变数据类型,所以 ln 中的值也发生了改变。

5.3 深拷贝

不可变数据类型的深浅拷贝一致。

复杂数据类型进行深拷贝会对数据中的所有元素完全重新复制一份,不管有多少层嵌套,互不影响。

import copy
ls = [1,2,3,['a', 'b']]
# 深拷贝使用deepcopy
ln = copy.deepcopy(ls)
ls[3][0]='b'
print(ls)
print(ln)

[1, 2, 3, ['b', 'b']]
[1, 2, 3, ['a', 'b']]

  • Python
    50 引用 • 197 回帖 • 1 关注
回帖
请输入回帖内容 ...