Python编程高手之路——第三章:数据类型

三、数据类型

3.1 数据类型

3.1.1 数字类型int和float

  • 数字类型即变量的值,如age=18,18就是我们保存的值;
  • 变量是用来反映/保存状态以及状态变化的,针对不同的状态应该用不同的数据去标识;
  • 数字类型只能存储一个值,是不可变类型(不可变类型可以哈希,后面的章节会讲解哈希)

3.1.2 int类型常用的方法

  • bin()、oct()、hex()在进制转换中经常用到;
print(bin(3))  # 十进制转成二进制,0b11
print(oct(8))  # 十进制转成八进制,0o10
print(hen(16))  # 十进制转成十六进制,0x10
  • 在进行用户交互程序的时候常用.isdigit()(该函数的功能是判断字符串是否全部只由数字组成,如果是,返回True,否则返回False)判断用户输入是不是数字来进行下一步操作。这样避免了程序出错。但是需要注意用户输入的内容默认是字符串,判断一个字符串是否是数字,可以使用下面的方法。
age = input("your age>>:")
if age.isdigit():
    age = int(age)
    age += 1
print(age)

3.1.3 Python其它数字类型(了解)

  • #int(整型)

    • 在32位机器上,整数的位数为32位,取值范围为 − 2 31 -2^{31} 231 2 31 − 1 2^{31}-1 2311,即-2147483648到2147483647。
    • 在64位机器上,整数的位数为64位,取值范围为 − 2 63 -2^{63} 263 2 63 − 1 2^{63}-1 2631,即-9223372036854775808到9223372036854775807。
  • #long(长整型)

    • 和C语言不同,Python的长整型没有指定位宽,即Python没有限制长整数数值的大小。
    • 自从Python2.2起,如果整数发生溢出,Python会自动将整数数据转换为长整数,所以在长整型数据之后不加字符long;
    • 在Python3里不再有long类型,全都是int。
  • #complex(复数型)
    -和数学上的复数是一样的。

a = 2 ** 64  # 长整型,但是数据类型仍然是int型

x = 1-2j  # 复数
x.img = 2  # 复数的虚部为2,使用.ing求复数的虚部
x.real = 1  # 复数的实部为1,使用.real求复数的实部

3.2 字符串类型

3.2.1 字符串类型介绍

  • 在python中,加了引号的字符就是字符串类型,用于标识:描述性的内容,如姓名,性别,国籍,种族,定义形式;
  • 字符串格式化:
name = input('请输入名字>>:')
print('你好,%s' % name)  # %s可以理解为占位符,在输出时会使用字符串后面的%后面的变量的值进行替换

3.2.2 单引号,双引号和三引号的区别

  • 单引号、双引号是没有区别的,但是当字符串中用到单引号时,整个字符串需要用到双引号;
  • 用到多行字符串时必须使用多引号;
msg = "I'm 18 years old!"

mes = 
'''
今天我想写首小诗,
歌颂我的同桌。
你看他那乌黑的短发,
好像一只炸毛鸡。
'''

3.2.3 字符串的拼接

  • 字符串能进行相加和相乘的操作;相加是将两个字符串拼接起来;相乘是将一个字符串进行多次复制然后拼接起来;
name = 'albert'
age = '18'
name + age => 'albert18'
name*5 => 'albertalbertalbertalbertalbert'

注意:

  • 字符串1+字符串2,并不会在字符串1的基础上加字符串3。而是申请一个全新的内存空间存入字符串1+字符串2;
  • 只能进行字符串+字符串,不能字符串+其它类型数据;

字符串类型只能存储一个值,是一个不可变类型,可以哈希;

3.3.4 字符串类型常用方法

(1)按照索引取值

字符串是不可变类型,并不能改变字符串的值,取值时最多可以有三个参数,分别是起始位置,结束位置和步长。可以正向取值或反向取值。步长为-1表示从最后一个元素开始取值。步长可以为负数。

hobbies = 'music basketball'
hobbies[0]
hobbies[0:5]
hobbies[0:5:2]  # 从第0个元素到第4个元素,隔一个元素取一次值
hobbies[0:5:-2]  # 取不到元素,因为从第0个元素到第4个元素,逆序隔一个元素取一次值
hobbies[11:5:-2]  # 从第11个元素到第6个元素,逆序隔一个元素取一次值
hobbies[-1]  # 取倒数第一个字符
(2)长度运算
len('name')  # 用来求string类型,列表等的长度
(3)成员运算
print('a' in 'Albert')  # 判断a是否在Albert中,在则返回True,否则返回False
# 输出为False
print('a' not in 'Albert')
# 输出为True
(4)移除空白
print('   name'.lstrip())  # 移除左边空白
print('name   '.rstrip())  # 移除右边空白
print('  naem  '.strip())  # 移除两端空白
(5)切分

切分的作用是根据给定的切分规则将一段字符串切分开,并以列表的形式返回;

print('kobe 24 lakers'.split(' '))  # 返回为['kobe', '24', 'lakers']
print('kobe/24/lakers'.split('/',1))  # 1表示仅切分一次,返回为['kobe', '24/lakers']
print('kobe/24/lakers'.rsplit('/',1))  # 表示从右往左进行切分
(6)组合
print('a'.join('1234'))  # 输出为1a2a3a4
tag = ' '
print(tag.join(['I','say','hello','world']))  # 输出为I say hello world
(7)替换
print('abc name id'.replace('a','card'))  # 将前面字符串中的a全部替换为'card'

3.3 列表

3.3.1 列表类型基本介绍

在[]内用括号分割,可以存放n个任意类型的值,用于标识:存储多个值的情况。

students = ['albert', 'james', 'kd']

列表可以存储多个值,是有序的,是可变类型·,不可以哈希;

3.3.2 列表类型常用的方法

(1)添加元素
  • append方法,在列表最后追加元素
l1 = ['a', 'b', 'c', 'd', ]
l1.append('e')  # 输出为['a', 'b', 'c', 'd', 'e']
l1.append(['a', 'b', 'c', 'd', ])  # 输出为['a', 'b', 'c', 'd', 'e', ['a', 'b', 'c', 'd']]
  • insert方法,在列表中插入元素
l1 = ['a', 'b', 'c', 'd', ]
l1.insert(3, 'x')  # 输出为['a', 'b', 'c', 'x', 'd']
  • extend方法,在列表中同时插入多个元素,extend方法使用和append方法的区别(append是整体添加,extend是逐个添加)
l1 = ['a', 'b', 'c', 'd', ]
l1.append(['a', 'b', 'c', 'd', ])  # 输出为['a', 'b', 'c', 'd', 'e', ['a', 'b', 'c', 'd']]

l1 = ['a', 'b', 'c', 'd', ]
l1.extend(['a', 'b', 'c', 'd', ])  # 输出为['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd']
  • extend在执行添加的时候,被传入的参数必须是可迭代对象,这样通过迭代就解决了同时传入多个参数的问题。
l1 = ['a', 'b', 'c', 'd', ]
l1.extend('abc')  # 输出为['a', 'b', 'c', 'd', 'a', 'b', 'c']

l1 = ['a', 'b', 'c', 'd', ]
l1.append('abc')  # 输出为['a', 'b', 'c', 'd', 'a', 'b', 'c', 'abc']

l1 = ['a', 'b', 'c', 'd', ]
l1.extend('a')  # 输出为['a', 'b', 'c', 'd', 'a', 'b', 'c', 'a']
(2)删除元素
  • pop删除,有返回值,默认删除列表中最后一个,指定删除索引值;
l1 = [1, 2, 3, 4, 5, 6, ]
print(l1.pop())  # 删除列表中的某个元素,默认是最后一个元素,这个是有返回值的,返回值为6;
print(l1)  # 输出为[1, 2, 3, 4, 5]
print(l1.pop(2))  # 删除索引为2的地方的值,返回值为3
print(l1)  # 输出为[1, 2, 4, 5]
  • remove删除,没有返回值,没有默认值,指定被删除的元素,不是指定索引,是指定的值;
l1 = [1, 2, 3, 4, 5, 6, ]
print(l1.remove(2))  # 删除列表中值为2的数据
print(l1)  # 输出为[1, 3, 4, 5, 6]
  • clear删除,保留列表名称,清空里面的值;
l1 = [1, 2, 3, 4, 5, 6, ]
l1.clear()
print(l1)  # 输出为[]
  • del删除,通用删除,但是一般不用;
l1 = [1, 2, 3, 4, 5, 6, ]
del l1[2]  # 删除索引为2的内存存储的值,输出为[1, 2, 4, 5, 6]
del l1
print(l1)  # 输出为NameError: name 'l1' is not defined
(3)更改元素
  • 注意与insert插入的不同,都是以原来的位置为参考,insert是挤开,本质是添加,而这里是替换;
l1 = [1, 2, 3, 4, 5, 6, ]
l1[2] = 4
print(l1)  # 输出为[1, 2, 4, 4, 5, 6]
(4)查找元素
  • 按照索引或者指定列表中的元素查找
l1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(l1.index('a'))  # 返回'a'在l1的索引值
print(l1.index('b', 1, 4))  # 检索的起始位置和终止位置
  • 把列表分段查找
l1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
a = int(len(l1)/2)
print(l1[:a])  # 输出为['a', 'b', 'c']
print(l1[a:])  # 输出为['d', 'e', 'f', 'g']
  • 使用enumerate对列表枚举
l1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
for i, x in enumerate(l1, 100):  # 100的意思是将100指定为枚举开始的位置
    print(i, x)  # i是索引的地址,x是对应的列表中的值
# 输出为
100 a
101 b
102 c
103 d
104 e
105 f
106 g
(5)统计长度
print(len([1,2,3,4,]))
(6)统计元素个数
print(['a','b'].count('a'))
(7)排序
  • resverse 反序排序
l1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
l1.reverse()
print(l1)  # 输出为['g', 'f', 'e', 'd', 'c', 'b', 'a']
  • sort 按照ASCII码来进行排序
l1 = ['a', '1', 'b', 'c', 'd', 'e', 'f', 'g']
l1.sort()
print(l1)  # 输出为['1', 'a', 'b', 'c', 'd', 'e', 'f', 'g']
l1.sort(reverse=True)  # 输出为['g', 'f', 'e', 'd', 'c', 'b', 'a', '1']
print(l1)
(8)复制列表
l1 = ['a', '1', 'b', 'c', 'd', 'e', 'f', 'g']
print(l1.copy())  # 输出为['a', '1', 'b', 'c', 'd', 'e', 'f', 'g']
(9)Python中的赋值、浅拷贝和深拷贝的区别
  • 赋值:对于复制的操作,最简单的就是赋值,指的是新建一个对象的引用,新建目标对象与原来的目标对象指向同一个内存地址。因而始终保持一致。
l1 = [1, 2, 3, 4, 5, [6, 7, 8, ]]
l2 = l1
l1.append(9)
print(l1)  # 输出为[1, 2, 3, 4, 5, [6, 7, 8], 9]
print(l2)  # 输出为[1, 2, 3, 4, 5, [6, 7, 8], 9]
l1[5][0] = 10
print(l1)  # 输出为[1, 2, 3, 4, 5, [10, 7, 8], 9]
print(l2)  # 输出为[1, 2, 3, 4, 5, [10, 7, 8], 9]
l1[5] = 10
print(l1)  # 输出为[1, 2, 3, 4, 5, 10, 9]
print(l2)  # 输出为[1, 2, 3, 4, 5, 10, 9]
  • 浅拷贝:浅拷贝顾名思义就是拷贝的比较浅,可以把赋值认为是新建了一个对象的引用,把原来被对象内存空间的数据指向新的变量,这时同一块内存空间指向两个变量,浅拷贝和赋值不同。既然是拷贝,那么就是要开辟一块新的内存空间,复制的是原来被拷贝对象内多个元素对象的引用,有几个元素对象就赋值几个元素对象的引用。因此,被浅拷贝对象内的元素改变,会引起浅拷贝对象内元素的改变;被拷贝对象添加元素,拷贝对象不再添加元素(因为没有一个新的引用);被拷贝对象删除元素,拷贝对象也删除元素(元素搜已经删除了,虽然引用存在,但是并没有什么用)。
  • 深拷贝:深拷贝其实与浅拷贝有本质的区别,它不会复制任何的引用,对象内的所有元素,子元素,孙子元素,重孙元素,曾孙元素的数据都是复制而来。它的实现原理是递归,只要任意元素内仍然有子元素,就会复制子元素的数据放到新的内存地址。既然这样,在使用深拷贝后,被拷贝对象的改变,不会引起拷贝对象的任何改变。

复制与深浅拷贝的总结

  • 赋值:新建一个原来对象内存地址的引用,不开辟新的内存空间;
  • 浅拷贝:新建多个原来对象内一级子元素内存地址的引用,开辟新的内存地址;
  • 深拷贝:复制原来对象内的所有N级子元素的数据,开辟新的内存空间;

3.4 元组

  • 与列表类型相比,非常类似只不过把[]变成(),作用是用于存储多个值,对比列表来说,元组不可变(是可以当做字典的key的),不可改变,主要是用来读;
  • 元组可以存储多个值,是有序的,是不可变类型,可以哈希。元组常用的方法,可以参考列表常用方法,需要注意的是,元组只能取值,不能改变元组的值。

3.5 字典

3.5.1 字典类型基本介绍

字典用于存放一个人的信息:姓名,性别,年龄,很明显是多个值,既然是存多个值,我们完全可以基于刚刚学习的列表去存放,如下:

info = ['albert','male',18]

既然如此,为什么还需要字典呢?定义列表的目的不单单是为了存储,还要考虑取值,但是如果想取出这个人的年龄,可以用info[2]。

但是这是基于我们已经知道在第3个位置存放的是年龄的前提下,我们才知道索引2对应的是年龄,而这完全只是一种假设,并没有真正意义上规定第三个位置存放的是年龄。于是我们寻求一种,既可以存放多个任意类型的值,又可以硬性规定值的映射关系的类型,这就用到字典。

字典用于标识存储多个值的情况,每个值有唯一一个对应的key,可以更为方便高效地取值,字典的格式定义如下:

# 在{}内用逗号分隔,可以存放多个key:value值,key一般是字符串,value可以是任意类型
info = {'name':'albert','age':18,'sex':18}

字典可以存储多个值,是无序的,是可变类型,不可哈希。

3.5.2 字典类型常用的方法

(1)增加元素

通过键值对

l1 = {'name':'albert', 'age':18,'gender':'male'}
l1['hobbies']='music'
print(l1)

# 输出为{'name': 'albert', 'age': 18, 'gender': 'male', 'hobbies': 'music'}

用fromkeys构造一个字典

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
a = l1.fromkeys(l1, 'I am Albert')
print(a)
# {'name': 'I am Albert', 'age': 'I am Albert', 'gebder': 'I am Albert'}

b = dict.fromkeys('name')
print(b)
# {'n': None, 'a': None, 'm': None, 'e': None}

b = dict.fromkeys('e')
print(b)
# {'e': None}

b = dict.fromkeys(1)  # 报错,数字类型不可迭代
print(b)
# TypeError: 'int' object is not iterable

b = dict.fromkeys([1, 2, 3, ])
print(b)
# {1: None, 2: None, 3: None}
(2)删除元素

del 通过字典的key删除

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
del l1['name']
print(l1)
# {'age': 18, 'gebder': 'male'}

pop或者popitem删除

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
res = l1.pop('name')  # 删除指定key的value,并拿到一个返回值
print(res)
# albert
print(l1)
# {'age': 18, 'gebder': 'male'}

res2 = l1.popitem()  # 随机返回并删除字典中的一对键和值(一般删除末尾对)
# 如果字典已经为空,却调用了此方法,就报出KeyError异常
print(res2)
# ('gebder', 'male')
print(l1)
# {'age': 18}
(3)更改元素

通过键值对的方式

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
l1['name'] = '马一特'
print(l1)
# {'name': '马一特', 'age': 18, 'gebder': 'male'}

通过setdefault或者update操作,两者使用和区别如下:

  • setdefault只添加不修改
d1 = {'name': 'albert', 'age': 18, }
d1.setdefault('name', 'Albert')
d1.setdefault('gender', 'male')
print(d1)
# {'name': 'albert', 'age': 18, 'gender': 'male'}
  • update既添加也修改
d1 = {'name': 'albert', 'age': 18, }
d1.update({'name': 'Albert', 'gender': 'male'})
print(d1)
# {'name': 'Albert', 'age': 18, 'gender': 'male'}
(4)查找元素

通过键值对查找

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
a = l1['name']
print(a)
# albert

通过get方法查找

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
a = l1.get('hobbies')  # 找不到不报错
print(a)
# None

通过enumerate枚举

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
for a in enumerate(l1):
    print(a)
# (0, 'name') (1, 'age') (2, 'gebder')

通过.key(),.values(),.items()等方法

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}

a = l1.keys()
print(a)
# dict_keys(['name', 'age', 'gebder'])
print(list(a)[0])
# name

a = l1.values()
print(a)
# dict_values(['albert', 18, 'male'])
print(list(a)[0])
# albert

a = l1.items()
print(a)
# dict_items([('name', 'albert'), ('age', 18), ('gebder', 'male')])
print(list(a)[0])
# ('name', 'albert')

通过for循环遍历

l1 = {'name': 'albert', 'age': 18, 'gebder': 'male'}
for k,v in l1.items():
    print(k,v)
# name albert
# age 18
# gebder male
(5)成员运算与长度运算

参考列表的运算方法,成员运算的依据是字典的key,而不是value,长度运算都可以作为参考的依据。

3.6 集合类型

花括号内,多个元素用逗号分割,用来存储多个值,并且是无序的,那么这多个值不能用来取值,但是可以用来进行去重(比如去掉列表中重复的元素)和关系运算。

集合的元素遵循三个原则:
  \space  
1:每个元素必须是不可变类型(可作为字典的key);
2:没有重复的元素;
3:无序;
  \space  
注意集合的目的是将不同值存放到一起,不同集合间用来做关系运算,无需纠结与集合中单个值。

集合类型可以存放多个值,是无序的,是可变类型,不可以哈希。

关系运算练习:
有以下两个集合,piano是报名钢琴课程的学员名字集合,violin是报名小提琴课程的学员名字集合。
piano = {‘albert’, ‘孙悟空’, ‘周星驰’, ‘朱茵’, ‘林志玲’}
violin = {‘猪八戒’, ‘郭德纲’, ‘林忆莲’, ‘周星驰’}
1、求出既报名钢琴又报名小提琴课程的学员名字集合;
2、求出所有报名的学生名字集合;
3、求出只报名钢琴课程的学员名字;
4、求出没有同时报名这两个课程的学员名字集合。

答案:

print(piano & violin)
print(piano | violin)
print(piano - violin)
print(piano ^ violin)

3.7 collections容器数据类型

(1)namedtuple命名元组

from collections import namedtuple

point = namedtuple('p', ['x', 'y'])  # p代表名称,x和y代表内容
p = point(1, 2)
print(p)
# p(x=1, y=2)
print(p.x)
# 1
print(p.y)
# 2

(2)deque超级列表

数据结构中比较常用的双向队列在python中可以使用deque实现。

collections容器类型一共有9种,除了上面介绍之外,还有ChainMap链映射,Counter计数字典,OrderedDict,defaultdict,UserDict,UserList,UserString。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值