变量及变量类型
1. 变量
什么是变量呢,我觉得很多人都回答不出来吧。
- 量:是衡量(记录)现实世界中的某种特征(状态)。
- 变:指的是记录的状态是可以发生变化的。
为什么要使用变量。
是为了让计算机能够像人一样去将一个事物的状态记忆下来,以后可以取出来进行使用。
Python 中怎么使用变量呢。
例如定义一个变量,变量名称为 name,值为 juzicoding,同时打印 name 这个变量。
name = 'juzicoding'
print(name)Python变量的参考命名规范。
- 见名知意。即别人看到你的命名即使没有注释也知道这个变量是用来干啥的,为了更好的区分这一点,通常项目中会使用
下划线拼接每一个单词(user_name),或者使用驼峰命名法(userName、UserName),目前我见到的Python项目中下划线规范的比较多。 - 变量名的第一个字符不能是数字。
- 变量名只能是字母、数字或下划线组成,并且区分大小写。
- 同时为了规范告诉其他人这个变量是常量不允许修改(只是规范,并不代表不可以修改),规范中通常会定义常量为全大写,单词之间使用
下划线拼接,例如USER_PASSWORD = 123456。
变量几个特点。
变量的值是存在内存中的,可以使用id(变量名)获取该变量在内存中的地址。观察一下,可以发现name没有赋值为juzicoding2之前内存中的地址是一直没有变的。
name = 'juzicoding'
USER_PASSWORD = 123456
print(id(name))
print(id(name))
name = 'juzicoding2'
print(id(name))
print(id(name))
print(id(USER_PASSWORD))变量是有类型的,经常使用的类型有字符串、数字、布尔、列表、元组、字典、集合,使用 type(变量名) 来获取变量的类型。
name = 'juzicoding'
# 输出结果 <class 'str'>,表示为字符串类型
print(type(name))2. 变量类型
每一个变量都会有变量类型,接下来就瞅瞅每种变量类型有什么作用,常用场景有哪些~
2.1 字符串
- 字符类型
<class 'str'> - 作用:记录描述性质的数据,比如人的名字、性别、家庭地址、公司简介、提示信息等。
- 定义:在引号内按照从左到右的顺序依次包含一个个字符,引号可以是单引号、双引号、三引号,通常情况下使用单引号。
字符串的定义
# 例如定义name
name1 = 'juzicoding'
name2 = "juzicoding"
name3 = '''juzicoding'''
print(name1, name2, name3)常用方法
字符串拼接。使用 + 拼接,* 重复打印多个字符串。
print('juzicoding' + 'blog')
print('juzicoding' * 10)通过索引来取出字符串中对应位置上的字符,从左到右索引从0开始,从右到左索引从-1开始。
tips_str = 'abcdef'
# 取出第1个英文字符
print(tips_str[0])
# 取出第2个英文字符
print(tips_str[1])
# 取出倒数第1个英文字符
print(tips_str[-1])
# 取出倒数第2个英文字符
print(tips_str[-2])从键盘输入。print是输出,那么需要从键盘输入使用input。
# 特别注意:input(提示用户的输入信息) 输入的数据都会变成字符串类型
# 例如需要输入用户名密码
user_name = input('请输入你的用户名:')
password = input('请输入你的密码:')
print('键盘输入的用户名为:' + user_name + ", 变量类型: " + str(type(user_name)))
print('键盘输入的密码为:' + password + ", 变量类型: " + str(type(password)))字符串使用大量+拼接,显然不够优雅,这个时候就需要使用字符串格式化输出了。
需要格式化字符串和数字的情况下,同时不需要重复多次输出某个变量的时候,适合%格式化输出。
# %s占位符:可以接收所有数据类型
# %d占位符:可以接收整数类型,通常整数使用%s占位符即可
# %f 占位符:可以接收数字类型,默认保留六位小数,不足时补 0;也可以指定保留多少位小数。
# 比如要求用户输入用户名、性别,然后打印以下格式
name = input('请输入你的姓名: ')
sex = input('请输入你的性别: ')
# 单个占位符在%号后面加入需要填入的变量即可
print('我的姓名是%s' % name)
# 多个占位符在%号后面使用括号包裹,按顺序传入
print('我的姓名是%s,性别%s' % (name, sex))
# 需要格式化小数、保留指定位数时,使用 %f,不足位数再补 0
# 不限定保留位数时,不足位数补充0,结果为3.141500
print('%f' % 3.1415)
# 保留1位小数,结果为3.1
print('%.1f' % 3.1415)
# 保留3位小数,结果为3.142
print('%.3f' % 3.1415)
# 保留5位小数,同样不足位数填充0,结果为3.14150
print('%.5f' % 3.1415)除了 %s、%d、%f,%x 可以格式化十六进制整数;如果字符串中需要输出一个普通的 % 字符,要写成 %% 转义:
# ff
print('%x' % 255)
# growth rate: 7 %
print('growth rate: %d %%' % 7)当然如果需要一个变量的值输出多次,还可以使用format格式化,文章后面会提到。
2.2 数字
- 数字类型,分为整型
<class 'int'>和浮点型<class 'float'>。 - 作用:记录年龄、等级、QQ 号、各种号码
- 定义:
age = 18
age = 18
# 结果为<class 'int'>
print(type(age))
# 浮点型 float
# 作用:记录身高、体重 weight、薪资
weight = 151.2
# 结果为<class 'float'>
print(type(weight))算术运算符的使用。
# 加 +
print(2 + 2)
# 减 -
print(2 - 2)
# 乘 *
print(2 * 7)
# 除 /
# 2.0
print(4 / 2)
# 1.6666666666666667
print(5 / 3)
# 整除 // 结果为2
print(4 // 2)
# 求余 % 结果为1
print(7 % 2)
# 乘方 ** 结果为16
print(4 ** 2)数字字面量的常见写法
除了普通的十进制写法,Python 还支持其他几种表示方式:
# 十六进制,以 0x 开头,使用 0-9 和 a-f
# 255
print(0xff)
# 2780087250
print(0xa5b4c3d2)
# 数字中间可以用下划线分隔,便于阅读大数字
# 10000000000
print(10_000_000_000)
# 十六进制同样支持下划线
print(0xa1b2_c3d4)
# 很大或很小的浮点数使用科学计数法,用 e 表示 10 的幂
# 1230000000.0
print(1.23e9)
# 1.2e-5 的值等于 0.000012,但默认打印会显示为科学计数法
print(1.2e-5) # 1.2e-05Python 的整数没有大小限制,想写多长写多长;浮点数超过 float 能表示的最大值(约 1.8e308)时会显示为 inf(无限大),下溢时则显示为 0.0。
比较运算符的使用,条件成立返回 True,不成立返回 False。
# 等于 ==
# False
print(3 == 4)
# True
print(3 == 3)
# 不等于 !=
# False
print(3 != 3)
# True
print(3 != 4)
# 大于 >
# True
print(3 > 2)
# 小于 <
# False
print(3 < 3)
# 大于等于 >=
# True
print(4 >= 4)
# 小于等于 <=
# True
print(4 <= 5)
# 类型为布尔类型,<class 'bool'>
print(type(4 <= 5))
# 当被单引号包裹时为字符串类型,不构成比较运算符关系,<class 'str'>
print(type('4 <= 5'))2.3 布尔
- 布尔类型
<class 'bool'> - 作用:用于条件判断,即判断一个条件成立时,用 True 表示,不成立则用 False 表示。
- 定义:
flag = True
# 判断条件是否成立
tag = 1 > 0
# 输出True
print(tag)
# <class 'bool'>
print(type(tag))2.4 列表
前面提到的字符串、数字、布尔类型都是单个的值,那么需要保存多个值的时候就需要用到列表、元组、字典、集合了。
- 列表类型
<class 'list'> - 作用:记录/存储多个值,列表是有序的,可以方便地取出来指定位置的值,比如人的多个爱好,一堆学生姓名。
- 定义:在
[]内用逗号分隔开多个任意类型的值,当然在绝大多数情况下一个列表会记录同一种类型的数据,通常用于对这一列表中同一类型的数据进行逻辑处理。
# 定义列表,字符串、数字、元组混合
my_list = ['name', 'juzicoding', 'age', 18, [1, 2, 3]]
# ['name', 'juzicoding', 'age', 18, [1, 2, 3]]
print(my_list)
# <class 'list'>
print(type(my_list))
# 使用下标可以取出列表中对应位置的值
# 正向取值,下标从0开始,依次递增
# name
print(my_list[0])
# juzicoding
print(my_list[1])
print(my_list[2])
print(my_list[3])
# [1, 2, 3]
print(my_list[4])
# 反向取值,下标从-1开始,依次递减
# [1, 2, 3]
print(my_list[-1])
# 取出列表中的列表第1个元素,1
print(my_list[-1][0])
# 取出列表中的列表第2个元素,2
print(my_list[-1][1])
# 18
print(my_list[-2])
# age
print(my_list[-3])
# 对列表中对应下标的值进行重新赋值,例如把'name'修改成'domain','juzicoding'修改为'juzicoding.com'
my_list[0] = 'domain'
my_list[1] = 'juzicoding.com'
# ['domain', 'juzicoding.com', 'age', 18, [1, 2, 3]]
print(my_list)2.5 元组
- 元组类型
<class 'tuple'> - 作用:与列表功能类似,区别在于元组定义好之后不能修改里面的值,适用于只读不修改的情况。
- 定义:在
()内用逗号分隔开多个任意类型的值,当然在绝大多数情况下一个元组会记录同一种类型的数据,通常用于对这一元组中同一类型的数据进行逻辑处理。
# 定义元组,字符串、数字、列表混合
user_tuple = ('name', 'juzicoding', 'age', 18, [1, 2, 3])
# ('name', 'juzicoding', 'age', 18, [1, 2, 3])
print(user_tuple)
# <class 'tuple'>
print(type(user_tuple))
# 使用下标可以取出元组中对应位置的值
# 正向取值,下标从0开始,依次递增
# name
print(user_tuple[0])
# 1
print(user_tuple[-1][0])
# 修改元组的值会报错
# Traceback (most recent call last):
# File "/Users/juzi/PycharmProjects/python-hello/main.py", line 17, in <module>
# user_tuple[0] = 'domain'
# TypeError: 'tuple' object does not support item assignment
user_tuple[0] = 'domain'元组的两个陷阱
第一个陷阱是「单元素元组」。定义只有一个元素的元组时,如果写成 (1),Python 会把它当成数学上的小括号,结果是整数 1 而不是元组。必须加一个逗号 (1,) 来消除歧义:
# 这不是元组,是整数
t = (1)
# 1
print(t)
# <class 'int'>
print(type(t))
# 加一个逗号才是元组
t = (1,)
# (1,)
print(t)
# <class 'tuple'>
print(type(t))第二个陷阱是「可变的元组」。元组的不可变指的是每个元素指向的对象不能变,但元素指向的对象本身如果是可变的(比如列表),内容还是可以修改的:
t = ('a', 'b', ['A', 'B'])
# 修改元组中列表的内容
t[2][0] = 'X'
t[2][1] = 'Y'
# ('a', 'b', ['X', 'Y'])
print(t)表面上看元组「变了」,其实变的是列表里的内容,元组本身并没有被替换任何元素,它始终指向同一个列表对象。
2.6 字典
- 字典类型
<class 'dict'> - 作用:记录多个
key : value值,优势是每一个值value都有其对应关系/映射关系key,而key对value有描述性的功能。 - 定义:在
{}内用逗号分隔开多个key : value元素,其中 value 可以是任意的数据类型,而 key 必须是可哈希(hashable)类型;字符串是最常用的 key 类型,数字、元组等不可变类型也可以作为 key。
# 定义字典
user_dict = {'name': 'juzicoding', 'password': 123456}
# {'name': 'juzicoding', 'password': 123456}
print(user_dict)
# <class 'dict'>
print(type(user_dict))
# 取出key对应的value
# juzicoding
print(user_dict['name'])
# 123456
print(user_dict['password'])
# 取一个不存在的key会报错
# print(user_dict['age'])
# 对字典类型的值进行修改
user_dict['name'] = 'juzicoding@qq.com'
# {'name': 'juzicoding@qq.com', 'password': 123456}
print(user_dict)
# key 必须是可哈希对象:字符串、数字、元组都可以
# 而列表、字典、集合等可变对象不能作为 key
ok_dict = {(1, 2): '元组可以作为 key'}
print(ok_dict[(1, 2)]) # 元组可以作为 key
# 下面这行会报错:TypeError: unhashable type: 'list'
# bad_dict = {[1, 2]: '列表不能作为 key'}2.7 集合
- 集合类型
<class 'set'> - 作用:通常用于关联操作,求交集、差集、并集。
- 定义:在
{}内用逗号分隔开多个元素,元素是无序的,集合中的元素必须是可哈希(hashable)对象,因此字符串、数字、布尔、元组等不可变类型可以放入,而列表、字典、集合等可变类型不能放入,否则会报错;同时元素不能重复,如果重复会对相同的值去重。
# 定义集合
user_set1 = {'name', 'juzicoding', 'age', (1, 2, 3), 18}
user_set2 = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
user_set3 = {'name', 'juzicoding', 'age', (3, 2, 1), 18, 19}
# <class 'set'>
print(type(user_set1))
# 可以观察到三个集合输出每次的顺序可能都不一样,所以集合是无序的,也不能通过下标取出值来
print(user_set1)
print(user_set2)
print(user_set3)
print('--------------华丽的分割线--------------')
# 求交集,两个集合都存在的元素,是把集合里面的每个元素当做一个整体比较
# {'juzicoding', 'name', (1, 2, 3), 'age', 18}
print(user_set1 & user_set2)
# {'age', 18, 'name', 'juzicoding'}
print(user_set1 & user_set3)
# 求并集,把两个集合合并去重后的结果
# {'juzicoding', 'name', (1, 2, 3), 'age', 18}
print(user_set1 | user_set2)
# {'juzicoding', 'name', (1, 2, 3), 'age', (3, 2, 1), 18, 19}
print(user_set1 | user_set3)
# 求差集,A集合 - B集合的结果,即A集合不存在B集合中的元素
# {(1, 2, 3)}
print(user_set1 - user_set3)
# {(3, 2, 1), 19}
print(user_set3 - user_set1)2.8 列表、元组、字典、集合的区别
- 列表、元组是依靠索引取值;字典通过key来取值;集合通常用来取关系集合。
- 列表、字典中的值可以修改,列表通过
list[下标] = 值来修改值,字典通过dict[key] = 值来修改对应的值;元组不能修改,只能读;集合通常用来取关系集合不会单独读写。
总结来说,通常还会有以下分类~
- 数值类型(整型 int、浮点型 float)
- 序列类型,即有序、可通过下标访问的数据类型(列表 list、元组 tuple、字符串 str)
- 散列类型,不可以通过下标来取值(字典 dict 自 Python 3.7 起保留插入顺序,集合 set 无序)
2.9 再议不可变对象
「不可变对象」到底是什么意思,用字符串 replace() 方法演示一下最直观:
a = 'abc'
# Abc
print(a.replace('a', 'A'))
# abc,a 本身没有变化
print(a)replace() 看起来是「替换」,但它并没有修改字符串 'abc',而是创建了一个新字符串 'Abc' 并返回。要想拿到替换结果,需要把返回值赋值给变量:
b = a.replace('a', 'A')
# Abc
print(b)记住:不可变对象调用自身的方法,不会改变对象本身,而是创建新对象返回。这和列表的 sort()、append() 直接在原对象上修改完全不同。理解了这一点,也就明白了为什么列表、字典不能作为字典的 key 或集合的元素,而字符串、数字、元组可以。
3. 变量类型常用操作/方法
变量当然会有一些贴合业务操作常用的方法,如果什么都要自己封装方法,那么 Python 也不可能成为一门流行的语言,接下来就来瞅瞅和变量类型相关常用的方法。
3.1 字符串的常用操作
len(string) 计算长度。
site_name = 'juzicoding blog'
# 15
print(len(site_name))string[起始下标:终止下标:步长] 切片,顾头不顾尾,查找字符串中的一段值,用于截取某些字符。
site_name = 'juzicoding blog'
# juzic
print(site_name[0:5])
# jzc
print(site_name[0:5:2])
# jzcdn lg 等价于 site_name[0:15:2]
print(site_name[0::2])
print(site_name[0:len(site_name) + 1:2])
# golb gnidocizuj 步长为负数,等价于 site[14::-1]
print(site_name[::-1])
print(site_name[len(site_name)::-1])in 和 not in 判断字符串的包含关系,返回结果为 True 和 False。
# in判断,当包含时返回True,结果为True
print('juzicoding' in site_name)
# not in判断,当不包含时返回True,结果为False
print('juzicoding' not in site_name)string.format(string1, string2) 字符串格式化,除 % 号之外,使用 format 格式化,可以多次复用同一个值。
# 我的名字是橘子coding
print('我的名字是{}'.format('橘子coding'))
# 我的名字是橘子 coding,橘子 coding 网址是 juzicoding.com
print('我的名字是{0},{0}的网址是{1}'.format('橘子coding', 'juzicoding.com'))
# 我的名字是橘子 coding,网站地址是 juzicoding.com
print('我的名字是{},网站地址是{}'.format('橘子coding', 'juzicoding.com'))
print('我的名字是{1}, 网站地址是{0}'.format('juzicoding.com', '橘子coding'))
print('我的名字是{name}, 网站地址是{domain}'.format(name = '橘子coding', domain = 'juzicoding.com'))f-string 是 Python 3.6 引入的格式化方式,写法最简洁:在字符串前加 f 前缀,字符串内用 {变量名} 直接引用变量,是目前最推荐的方式。
name = '橘子coding'
age = 18
# 我的名字是橘子coding,今年18岁
print(f'我的名字是{name},今年{age}岁')
# {变量:格式说明符} 可以指定格式,冒号后面的部分和 % 格式化规则一致
r = 2.5
# 半径 2.5 的圆面积是 19.62
print(f'半径 {r} 的圆面积是 {3.14 * r ** 2:.2f}')
# 3.1
print(f'{3.1415:.1f}')三种格式化方式对比,易用性上 f-string > format > %,日常开发优先使用 f-string。
string.join(list) 使用指定字符拼接列表元素。
str1 = '千里之行'
str2 = '始于足下'
str3 = '不积跬步'
str4 = '无以至千里'
# 千里之行, 始于足下, 不积跬步, 无以至千里
print(', '.join([str1, str2, str3, str4]))
# 千里之行 始于足下 不积跬步 无以至千里
print(' '.join([str1, str2, str3, str4]))del string 删除字符串,后续不再可以使用该变量。
test_del_str = 'delStr'
print(test_del_str)
del test_del_str
# 报错,NameError: name 'test_del_str' is not defined
print(test_del_str)大小写转换
# string.upper() 字符串变大写
msg = 'abc'
print(msg.upper())
# string.lower() 字符串变小写
msg = 'ABC'
print(msg.lower())
# string.capitalize() 字符串第一个字母变大写
msg = 'abc'
print(msg.capitalize())
# string.title() 字符串每个单词首字母变大写,以空白或非字母字符分隔
msg = 'abc edf'
print(msg.title())string.isupper() 判断字符串是否全为大写,是则返回True;string.islower() 判断字符串是否全为小写,是则返回True。
msg = 'ABC'
msg2 = 'abcDEF'
# True
print(msg.isupper())
# False
print(msg.islower())
# False
print(msg2.isupper())
# False
print(msg2.islower())string.split('分隔字符串') 以某个字符标识拆分字符串为列表。
address = '广东省,深圳市,南山区'
# ['广东省', '深圳市', '南山区']
address_list = address.split(',')
print(address_list)string.strip() 去除左右两边的字符,不管中间,不写去除字符时默认为空格。
msg = ' hello '
# hello
print(msg.strip())
# 传入参数时,去掉左右两边的指定字符
msg2 = '##hello##'
# hello
print(msg2.strip('#'))左右两侧不足指定位数时,添加指定的字符。
# ****wxe****
print('wxe'.center(10,'*'))
# wxe*******
print('wxe'.ljust(10,'*'))
# *******wxe
print('wxe'.rjust(10,'*'))string.find(sub_string)和string.index(sub_string) 查找字符串sub_string是否在string中的正序下标,find方法找不到时返回-1;index方法找不到时报错。
msg = 'abcdef'
# 1
print(msg.find('b'))
# -1
print(msg.find('g'))
# 1
print(msg.index('b'))
# 报错,ValueError: substring not found
print(msg.index('g'))string.count(string2) 统计一个字符串出现的次数。
msg = 'abcdef a'
# 2
print(msg.count('a'))string.isdigit() 判断字符串是否都是数字,是则返回True,否则返回False;string.isalpha() 判断字符串是否都是字母,是则返回True,否则返回False。
msg = 'abc'
msg2 = '123'
# False
print(msg.isdigit())
# True
print(msg2.isdigit())
# True
print(msg.isalpha())
# False
print(msg2.isalpha())string.startswith(start_string) 判断string是不是以start_string字符串开头;string.endswith(end_string) 判断string是不是以end_string字符串结尾。
msg = 'abcdef'
# True
print(msg.startswith('abc'))
# False
print(msg.endswith('gh'))转义字符,常用的有\n和\t,\n为换行,\t为制表符。
# a
# b
print('a\nb')
# a b
print('a\tb')3.2 数字的常用操作
赋值运算的缩写方式,例如 num1 = num1 + 2 可以缩写为 num1 += 2,以此类推。
# 普通赋值 =
# 加法赋值 +=
# 减法赋值 -=
# 乘法赋值 *=
# 除法赋值 /=
# 取余赋值 %=
# 乘方赋值 **=3.3 布尔的常用操作
特别注意,Python 中所有的数据都有对应的布尔值(真值),也就是说除了布尔类型本身,其他类型的有无也是布尔值。
None、0、空(空字符串、空列表、空元组、空字典、空集合)这三种情况下布尔值为 False;其他类型的其他值都为 True。
# False
print(bool(None))
# False
print(bool(0))
# True
print(bool(1))
# True
print(bool(1.1))
# False
print(bool(''))
# True
print(bool('juzicoding'))
# False
print(bool([]))
# True
print(bool([1, 2]))
# False
print(bool(()))
# True
print(bool((1, 2)))
# False
print(bool({}))
# True
print(bool({1, 2}))3.4 列表的常用操作
list[起始下标:终止下标:步长] 切片,顾头不顾尾,默认步长为1,和字符串提取字符一样,不同的是,字符串取的是字符,列表取的是一个元素;字符串不能通过下标修改值,列表可以更改。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
# [1, 2, 3]
print(my_list[0:3])
# [1, 2, 3]
print(my_list[0:3:1])
# [1, 3]
print(my_list[0:3:2])len(list) 列表元素的多少。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
print(len(my_list))in和not in 包含关系判断,in--存在时返回True;not in--不存在时返回True。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
# True
print(1 in my_list)
# False
print(1 not in my_list)list.count(element) 查看元素element在list中的个数。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
# 1
print(my_list.count(1))list.index(element) 在列表中从左至右查找指定元素element,找到了返回该值的下标,没有找到则报错。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
# 3
print(my_list.index(4))
# ValueError: 9 is not in list
print(my_list.index(9))list.append(element) 往列表末尾追加一个元素。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_list.append(9)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(my_list)list.extend(iterable) 往列表当中添加多个元素,参数为一个可迭代对象(如列表),同样为末尾追加。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_list.extend([9, 10])
# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(my_list)list.insert(index, element) 往指定下标位置index前插入一个元素element。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
my_list.insert(0, '-1')
# ['-1', 1, 2, 3, 4, 5, 6, 7, 8]
print(my_list)del list[index] 删除列表中的下标为index的元素。
my_list = [1, 2, 3, 4, 5, 6, 7, 8]
del my_list[0]
# [2, 3, 4, 5, 6, 7, 8]
print(my_list)list.remove(element) 删除列表中指定的元素element,如果存在重复元素仅会删除列表中的第一个元素。
my_list = [1, 2, 3, 4, 1, 2, 3, 4]
my_list.remove(3)
# [1, 2, 4, 1, 2, 3, 4]
print(my_list)list.pop() 从列表里面删除一个元素,同时返回被删除的元素,可以用变量接收,默认是删除最后一个元素。
my_list = [1, 2, 3, 4]
list_pop_last = my_list.pop()
# 4
print(list_pop_last)
# [1, 2, 3]
print(my_list)
# 使用下标拿走指定位置的值
res = my_list.pop(0)
# 1
print(res)
# [2, 3]
print(my_list)list.clear() 清空列表。
my_list = [1, 2, 3, 4]
my_list.clear()
# []
print(my_list)list.reverse() 列表反序,不会进行排序,只是对列表翻转。
my_list = [1, 2, 4, 3]
my_list.reverse()
# [3, 4, 2, 1]
print(my_list)list.sort(reverse = True/False) 对列表进行排序,排序时列表元素必须为同一类型,否则会报错,reverse = True为倒序;reverse = False为升序。
my_list = [1, 2, 4, 3]
my_list.sort(reverse = True)
# [4, 3, 2, 1]
print(my_list)
my_list.sort(reverse = False)
# [1, 2, 3, 4]
print(my_list)3.5 元组的常用操作
与列表方法(切片、获取长度、获取下标对应的值)没有什么区别,唯一不同的是元组不能修改元素的值,所以当需要修改元素的值时可以把元组转为列表来操作。
list(tuple) 把元组转化为列表。
my_tuple = (1, 2, 3, 4)
# 元组转列表,使用to_list变量接收
tuple_to_list = list(my_tuple)
# 转为列表后可以修改元素
tuple_to_list[0] = -1
# [-1, 2, 3, 4]
print(tuple_to_list)tuple(list) 把列表转为元组。
my_list = [1, 2, 3]
list_to_tuple = tuple(my_list)
# (1, 2, 3)
print(list_to_tuple)3.6 字典的常用操作
dict(key1 = value1, key2 = value2) 定义字典的第二种方法。
user_dict = dict(name = 'juzicoding', password = '123456')
# {'name': 'juzicoding', 'password': '123456'}
print(user_dict)len(dict) 获取字典长度,字典的长度为键的数量。
user_dict = dict(name = 'juzicoding', password = '123456')
# 2
print(len(user_dict))dict.get(key) 获取value,key不存在时不会报错(返回None),dict[key]当key不存在时会报错。
user_dict = dict(name = 'juzicoding', password = '123456')
# juzicoding
print(user_dict.get('name'))
# None
print(user_dict.get('age'))key in dict 判断key是否在字典dict中,存在则返回True;不存在则返回False。
user_dict = dict(name = 'juzicoding', password = '123456')
# False
print('age' in user_dict)
# True
print('age' not in user_dict)list(dict.keys()) 获取字典的所有key。
# ['name', 'password']
print(list(user_dict.keys()))list(dict.values()) 获取字典的所有value。
# ['juzicoding', '123456']
print(list(user_dict.values()))list(dict.items()) 获取字典所有的键值对。
# [('name', 'juzicoding'), ('password', '123456')]
print(list(user_dict.items()))dict[key] = value 字典的新增/更新操作,当key不存在时插入;key存在时更新value的值。
user_dict = dict(name = 'juzicoding', password = '123456')
user_dict['age'] = 18
# {'name': 'juzicoding', 'password': '123456', 'age': 18}
print(user_dict)
# 当字典key存在时则为更新操作
user_dict['name'] = 'wxe'
# {'name': 'wxe', 'password': '123456', 'age': 18}
print(user_dict)
# `dict.update({key: value})` 新增/更新另外一种写法,也是同样的效果
user_dict = dict(name = 'juzicoding', password = '123456')
user_dict.update({'name': 'wxe'})
# {'name': 'wxe', 'password': '123456'}
print(user_dict)
user_dict.update({'age': 18})
# {'name': 'wxe', 'password': '123456', 'age': 18}
print(user_dict)dict.setdefault(key, value) 当 key 存在时,不做修改并返回原 value;当 key 不存在时,插入对应的 key 和 value 并返回新 value。
user_dict = dict(name = 'juzicoding', password = '123456')
name = user_dict.setdefault('name', 'wxe')
# juzicoding
print(name)
# {'name': 'juzicoding', 'password': '123456'}
print(user_dict)
age = user_dict.setdefault('age', 18)
# 18
print(age)
# {'name': 'juzicoding', 'password': '123456', 'age': 18}
print(user_dict)dict.clear() 清空字典。
user_dict = dict(name = 'juzicoding', password = '123456')
user_dict.clear()
# {}
print(user_dict)del dict[key] 通过key删除字典中的元素,key不存在字典时会报错。
user_dict = dict(name = 'juzicoding', password = '123456')
del user_dict['name']
# {'password': '123456'}
print(user_dict)dict.pop(key) 通过key从字典删除一个元素,并且返回对应的value,可以用变量接收。
user_dict = dict(name = 'juzicoding', password = '123456')
password = user_dict.pop('password')
# 123456
print(password)
# {'name': 'juzicoding'}
print(user_dict)3.7 集合的常用操作
集合除了求差集等操作,对集合也可以进行操作。
in和not in 判断元素是否存在集合。
user_set = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
# False
print(19 in user_set)
# True
print(19 not in user_set)set.add(element) 集合新增元素。
user_set = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
# {'juzicoding', 18, 'age', (1, 2, 3), 'name'}
print(user_set)
user_set.add(19)
# {'juzicoding', 18, 19, 'age', (1, 2, 3), 'name'}
print(user_set)set.remove(element)和set.discard(element) 都是移除集合中的元素,不同的是remove当元素不存在时会报错,discard方法不会报错。
user_set = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
user_set.remove("name")
# {18, 'age', (1, 2, 3), 'juzicoding'}
print(user_set)
# 会报错,19这个元素不存在
# user_set.remove(19)
user_set.discard(19)
# {18, 'age', (1, 2, 3), 'juzicoding'}
print(user_set)set.clear() 清空集合。
user_set = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
user_set.clear()
# set()
print(user_set)set需要修改值时一般使用 remove + add 实现,例如把18修改为19的效果。
user_set = {'name', 'juzicoding', 'age', (1, 2, 3), 18, 18}
user_set.remove(18)
user_set.add(19)
# {19, 'juzicoding', 'age', (1, 2, 3), 'name'}
print(user_set)当然,我只列举了部分常用的,学无止境,还有很多方法可以自己研究~
4. 字符串和编码
Python 3 中,字符串类型 str 在内存里统一使用 Unicode 编码,这意味着可以表示世界上几乎所有字符。但字符串要保存到文件、通过网络传输时,就需要先编码成字节序列。
4.1 编码的演进:ASCII、Unicode 与 UTF-8
计算机只能处理数字,处理文本必须先给每个字符编一个号。最早只有 127 个字符被编码进计算机(大小写英文字母、数字和符号),这就是 ASCII 编码,1 个字节表示一个字符。
但世界上有上百种语言,各国都制定了自己的编码(中国有 GB2312、日本有 Shift_JIS、韩国有 Euc-kr),多语言混合的文本就会出现乱码。于是 Unicode 字符集应运而生,给每个字符分配一个唯一编号,把所有语言统一到一套编码里,彻底解决了乱码问题。
不过 Unicode 通常用 2 个字节表示一个字符,如果文本基本都是英文,存储和传输要浪费一倍空间。所以又出现了「可变长编码」UTF-8:英文字母编码成 1 个字节,汉字通常是 3 个字节,只有生僻字或补充字符才需要 4 个字节。UTF-8 兼容 ASCII,历史软件可以直接工作。
记住这套工作方式:内存里统一使用 Unicode,保存到磁盘或网络传输时转换为 UTF-8。
# 中文、英文、数字都可以正常表示
s = 'Python 3 你好'
print(s)
# <class 'str'>
print(type(s))4.2 bytes 类型
bytes 是字节类型,通常每个元素是一个 0-255 的整数。
# 英文字符可以直接写成 bytes
b = b'hello'
print(b) # b'hello'
print(type(b)) # <class 'bytes'>len() 对 str 计算的是字符数,对 bytes 计算的是字节数;bytes 中无法显示为 ASCII 字符的字节,会以 \x## 形式显示:
# 字符数
# 2
print(len('中文'))
# 1 个中文字符经 UTF-8 编码后通常占 3 个字节
# 6
print(len('中文'.encode('utf-8')))
# 字节数
# 6
print(len(b'\xe4\xb8\xad\xe6\x96\x87'))4.3 encode 和 decode
str 与 bytes 之间可以通过 encode() 和 decode() 互相转换。
s = '你好,Python'
# str -> bytes,使用 UTF-8 编码
b = s.encode('utf-8')
print(b) # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8cPython'
print(type(b)) # <class 'bytes'>
# bytes -> str,使用 UTF-8 解码
s2 = b.decode('utf-8')
print(s2) # 你好,Python
print(type(s2)) # <class 'str'>编码和解码必须使用同一种编码,否则会出现乱码或抛出
UnicodeDecodeError。
如果 bytes 中只有一小部分无效字节,解码时可以传入 errors='ignore' 忽略错误部分:
b = b'\xe4\xb8\xad\xff'
# 报错,UnicodeDecodeError
# print(b.decode('utf-8'))
# 忽略无效字节,结果为: 中
print(b.decode('utf-8', errors='ignore'))4.4 ord() 和 chr()
单个字符和它的整数编码之间可以互相转换:ord() 获取字符的整数表示,chr() 把整数编码转回字符。
# 65
print(ord('A'))
# 20013
print(ord('中'))
# B
print(chr(66))
# 文
print(chr(25991))如果知道字符的整数编码,还可以直接用十六进制 \u 前缀写字符串:
# 中文
print('\u4e2d\u6587')4.5 原始字符串 r'' 与多行字符串
字符串中 \ 是转义字符,\n 换行、\t 制表符。如果字符串里需要保留反斜杠本身,可以在字符串前加 r 前缀,表示「原始字符串」,内部不转义:
# 换行符
# a
# b
print('a\nb')
# 原样输出 \n 两个字符
# a\nb
print(r'a\nb')
# 文件路径、正则表达式等场景非常实用
# C:\Users\name
print(r'C:\Users\name')如果字符串内容需要跨多行,用 '''...''' 或 """...""" 包裹,可以保留换行格式:
msg = '''第一行
第二行
第三行'''
# 第一行
# 第二行
# 第三行
print(msg)原始字符串前缀 r 同样可以和多行字符串组合使用,比如 r'''hello\nworld'''。
4.6 文件编码
读取文本文件时建议显式指定 encoding='utf-8',否则在不同系统上可能使用默认编码,导致中文乱码。
with open('test.txt', 'w', encoding='utf-8') as f:
f.write('你好,Python')
with open('test.txt', 'r', encoding='utf-8') as f:
print(f.read())记住「Unicode 是内存里的字符表示,UTF-8 是存储和传输时的字节表示」,理解这一点就能避免大部分编码问题。