第三讲:基础数据类型与运算符
一、基础数据类型
1. 概念与分类
在Python这门语言中,数据类型分为两种: 内置和自定义
- 内置数据类型包括数字、字符串、布尔、列表、元组、字典、Bytes、集合以及一些不常用数据类型
- 自定义数据类型,一般以类的形式,根据需要与内置数据类型组合成为独特的数据类型
数据类型是Python语言非常重要的部分,尤其是不同数据类型所支持的原生操作,更是重中之重,需要熟练的背在脑海里。很多时候,写大型项目时,不需要你多复杂的技巧,只需要用这些数据操作方法就可以。
- 原因一,更好的分配管理内存,节省不必要的占用。如果没有数据类型的区别,那么所有的对象都必须按体积最大的对象所必须大小的房子分配空间,也就是内存空间,这样的浪费太严重了。有了数据类型,计算机就可以根据类型预定义的空间需求分配大小,合理开支。内存节省精简了,还能提高读取速度和运行效率。
- 原因二,方便统一管理,提供同样的API。这样,我们可以为同一数据类型,提供同样的操作,限制违规操作,也易于查找错误,定位问题。
- 原因三,区分数据类型,更贴切人类对自然事物的分类管理习惯。我们人类对事物都进行了各种分类,植物是植物、动物是动物,书是书,笔是笔。分类了之后,我们很自然的知道书可以读,笔可以写。数据类型也一样,让我们对抽象的数据有了可分辨的行为和自然的记忆。
2. 数值类型
数值类型是不可变类型**。**所谓的不可变类型,指的是类型值一旦不同,那么它就是一个全新的对象。
数字1和2分别代表两个不同的对象,对变量重新赋值一个数字类型,会新建一个数字对象。
>>> a = 1>>> print(id(a))1602842080>>> a = 2>>> print(id(b))Traceback (most recent call last):File "<pyshell#3>", line 1, in <module>print(id(b))NameError: name 'b' is not defined>>> print(id(a))1602842112>>> b=2>>> print(id(b))1602842112>>>
还是要强调一下Python的变量和数据类型的关系:
变量只是对某个对象的引用或者说代号、名字、调用等等,变量本身没有数据类型概念 。只有1,[1,2],”hello”这一类对象才具有数据类型的概念。
Python支持三种不同的数字类型:整数、浮点数和复数。
- 整数
整数通常被称为整型,数值为正或者负,不带小数点。Python 3的整型可以当做Long类型使用(Python 3 没有Python 2的Long类型)
- 表示数字的时候,通常使用十进制(decimal 英[ˈdesɪml]美[ˈdesɪml])来表示,有时我们还会用八进制(octonary 英 [‘ɒktə(ʊ)n(ə)rɪ]美 [‘ɑktə,nɛri] )或十六进制(hexadecimal 英 [ˌheksəˈdesɪml]美 [ˌheksəˈdesɪml])来表示:
- 十六进制用0x前缀和0-9,a-f表示,例如:0xff00
- 八进制用0o前缀和0-7表示,例如0o45
>>> hex(11) # 十进制转十六进制'0xb'>>> oct(11) # 十进制转八进制'0o13'>>> bin(11) # 十进制转二进制'0b1011'
整数内存:Python的整数长度为32位,并且通常是连续分配内存空间的。
>>> id(-2)1509059968>>> id(-1)1509060000>>> id(-1)-id(-2)32
小整数对象池
Python初始化的时候会自动建立一个小整数对象池,方便我们调用,避免后期重复生成!这是一个包含262个指向整数对象的指针数组,范围是-5到256。也就是说比如整数10,即使我们在程序里没有创建它,其实在Python后台已经悄悄为我们创建了。
为什么要这样呢?我们都知道,在程序运行时,包括Python后台自己的运行环境中,会频繁使用这一范围内的整数,如果每需要一个,你就创建一个,那么无疑会增加很多开销。创建一个一直存在,永不销毁,随用随拿的小整数对象池,无疑是个比较实惠的做法。
>>> id(-6)48311280>>> id(-5)1602841888>>> id(255)1602850208
- 整数缓冲区
除了小整数对象池,Python还有整数缓冲区的概念,也就是刚被删除的整数,不会被真正立刻删除回收,而是在后台缓冲一段时间,等待下一次的可能调用。
a = 100000print(id(a))del ab = 100000print(id(b))30288424916003028842491600
上面,我给变量a赋值了整数100000,看了一下它的内存地址。然后我把a删了,又创建个新变量b,依然赋值为100000,再次看下b的内存地址,和以前a存在的是一样的。
注意:在交互环境当中演示不出来效果。该效果在pycharm当中实现;并且注意不是小整数对象池当中的值。
- 浮点数
(floating 英[ˈfləʊtɪŋ] 美[ˈfloʊtɪŋ])
浮点数也就是小数,如1.23,3.14,-9.01,等等。但是对于很大或很小的浮点数,一般用科学计数法表示,把10用e替代,1.23x10^9就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等
- 复数
(complex 英[ˈkɒmpleks] 美[kəmˈpleks , ˈkɑːmpleks])
- 复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示,复数的实部a和虚部b都是浮点。
>>> a = 1>>> b = 2>>> complex(a,b) # a为实数部分,b为虚数部分(1+2j)
拓展:数学计算
更多的科学计算需要导入math这个库,它包含了绝大多数我们可能需要的科学计算函数,如下表
常用python内置函数
ceil(x) 返回数字的上入整数,如math.ceil(4.1) 返回 5exp(x) 返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045fabs(x) 返回数字的绝对值,如math.fabs(-10) 返回10.0floor(x) 返回数字的下舍整数,如math.floor(4.9)返回 4log(x) 如math.log(math.e)返回1.0,math.log(100,10)返回2.0log10(x) 返回以10为基数的x的对数,如math.log10(100)返回 2.0modf(x) 返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。pow(x, y) x**y 运算后的值。sqrt(x) 返回数字x的平方根acos(x) 返回x的反余弦弧度值。asin(x) 返回x的反正弦弧度值。atan(x) 返回x的反正切弧度值。atan2(y, x) 返回给定的 X 及 Y 坐标值的反正切值。cos(x) 返回x的弧度的余弦值。hypot(x, y) 返回欧几里德范数 sqrt(xx + yy)sin(x) 返回的x弧度的正弦值。tan(x) 返回x弧度的正切值。degrees(x) 将弧度转换为角度,如degrees(math.pi/2) , 返回90.0radians(x) 将角度转换为弧度
max(x1, x2,...) 返回给定参数的最大值,参数可以为序列。min(x1, x2,...) 返回给定参数的最小值,参数可以为序列。abs(x) 返回数字的绝对值,如abs(-10) 返回 10。round(x [,n]) 返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。
3. 布尔类型
(booleans 英[ˈbuːliənz] 美[ˈbuːliənz])
- 简介
对与错(0和1)、正与反,都是传统意义上的布尔类型。在Python语言中,布尔类型只有两个值,True与False(首字母要大写)。布尔值通常用来判断条件是否成立。 例如:
import randoma = int(input('请输入测试数据'))b = random.randint(0,1000)if a > b:print(f"a = {a} b = {b} \n a是一个大于3的数字")else:print(f"a = {a} b = {b} \n a不是一个大于3的数字")
拓展:random()函数
import randomprint( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数print( random.random() ) # 产生 0 到 1 之间的随机浮点数print( random.uniform(1.1,5.4) ) # 产生 1.1 到 5.4 之间的随机浮点数,区间可以不是整数print( random.choice('tomorrow') ) # 从序列中随机选取一个元素print( random.randrange(1,100,2) ) # 生成从1到100的间隔为2的随机整数a=[1,3,5,6,7] # 将序列a中的元素顺序打乱random.shuffle(a)print(a)import string# 随机整数:print random.randint(1,50)# 随机选取0到100间的偶数:print random.randrange(0, 101, 2)# 随机浮点数:print random.random()print random.uniform(1, 10)# 随机字符:print random.choice('abcdefghijklmnopqrstuvwxyz!@#$%^&*()')# 多个字符中生成指定数量的随机字符:print random.sample('zyxwvutsrqponmlkjihgfedcba',5)# 从a-zA-Z0-9生成指定数量的随机字符:ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))print ran_str# 多个字符中选取指定数量的字符组成新字符串:print ''.join(random.sample(['z','y','x','w','v','u','t','s','r','q','p','o','n','m','l','k','j','i','h','g','f','e','d','c','b','a'], 5))# 随机选取字符串:print random.choice(['剪刀', '石头', '布'])# 打乱排序items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]print random.shuffle(items)
bool()使用:Python内置的bool()函数可以用来测试一个表达式的布尔值结果。0、0.0、-0.0、空字符串、空列表、空元组、空字典,这些都被判定为False;而-1、”False”被判断为True。
>>> bool(1)True>>> bool(0)False>>> bool([])False>>> bool(())False>>> bool({})False>>> bool(-1)True>>> bool('')False>>> bool("False")True>>> bool("True")True>>> bool(0.0)False>>> bool(1.0)True>>> bool(-0.0)False
布尔类型运算:
and运算是与运算,只有所有都为True,and运算的结果才是True
>>> True and TrueTrue>>> True and FalseFalse>>> False and FalseFalse>>> 5 > 3 and 3 > 1True
or运算是或运算,只要其中有一个为True,or运算结果就是True
>>> True or TrueTrue>>> True or FalseTrue>>> False or FalseFalse>>> 5 > 3 or 1 > 3True
not运算是非运算,它是单目运算符,把True变成False,False变成True
>>> not TrueFalse>>> not FalseTrue>>> not 1 > 2True
在做四则运算的时候,把True看做1,False看做0
>>> True > FalseTrue>>> True < FalseFalse>>> True >=FalseTrue>>> True -10>>> True + 12>>> True *33>>> False -1-1
空值
空值不是布尔类型,严格的来说放在这里是不合适的,只不过和布尔关系比较紧密。空值是Python里一个特殊值,用None表示(首字母大写)。None不能理解为0,因为0是整数类型。None不是布尔类型,而是NoneType。
4. 字符串类型
(string 英[strɪŋ] 美[strɪŋ])
- 字符串的表示形式
abc可能是个变量,但是"abc"肯定是个字符串了。这里强调一下在编程语言中,所有的符号都是英文状态下的。
在Python中单引号和双引号的作用完全相同。在其他语言中,单双引号还是有一定区别的。
- 原生字符串:** 通过在字符串前加r或R**,如 r”this is test \n”,表示这个字符串里的斜杠不需要转义,等同于自身
- 字符串创建
字符串是Python中最常用的数据类型之一,使用单引号或双引号来创建字符串,使用三引号创建多行字符串。
s1 = "hello world"print(s1)s2 = 'hello nature'print(s2)s3 = '''hello city'''print(s3)
- 存储方式
字符串是不可变的序列数据类型,不能直接修改字符串本身,和数字类型一样!
>>> s2 = "hello world">>> s2[4] = 'l' #给字符串'hello world'中的第五个字母进行重新赋值,会出现错误提示Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: 'str' object does not support item assignment
对于数值类型而言,一个字节最大可存储的值是256,所以num就存储在一个字节当中。但是,字符串因本身是序列数据结构,所以num1为”200”的存储模式为”2””0””0”分别在存储在3个字节当中。如下
>>> num = 200>>> num1 = '200'>>> len(num)Traceback (most recent call last):File "<pyshell#5>", line 1, in <module>len(num)TypeError: object of type 'int' has no len()>>> len(num1)3>>> id(num)1602848448>>> id(num1)49075008>>>
**
- 字符串下标
由于字符串是序列数据结构,所以当我们要从”hello world”当中取出某一个字母就索引(默认从0开始)来取。
>>> s1 = "hello world">>> s1[1]'e'>>> s1[10]'d'>>> s1[-1]'d'>>> s1[11]Traceback (most recent call last):File "<stdin>", line 1, in <module>IndexError: string index out of range
**
- 字符串切片
在dos命令行中,输入help(slice),查看切片说明文档。
切片参数:
- start起始位置,默认索引从0开始
- stop结束位置,默认最后一个元素
- step步长,默认为1
- 切片区间为左闭右开形式
```python
help(slice) Help on class slice in module builtins:
class slice(object) | slice(stop) | slice(start, stop[, step]) | | Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).
**<a name="NTFwS"></a>#### 练习> - [x] test = "hello world",如何取出world值?```pythontest = 'hello world'print(test[-5::1]) #从倒数第五位开始取值,取到最后一位,步长为1print(test[::-1]) #倒叙输出字符串pring(test[::2]) #从第一个字母开始,按步长为2切片取值
**
- 字符串组成方式
+号直接拼接
>>> print('1' + '2')12
%s %d %f
>>> name = 'wei'>>> age = 18>>> print('姓名为:%s 年龄为:%d'%(name,age))姓名为:wei 年龄为:18
str.format()
>>> name = 'wei'>>> age = 18>>> print('姓名为:{} 年龄为:{}'.format(name,age))姓名为:wei 年龄为:18>>> print('姓名为:{1} 年龄为:{0}'.format(age,name))姓名为:wei 年龄为:18
f’’
>>> name = 'wei'>>> age = 18>>> print(f'姓名为:{name} 年龄为:{age}')姓名为:wei 年龄为:18
**
- 其它常见操作
S.find(sub) —> 返回该元素最小的索引
>>> test = 'hello python'>>> test.find('e')1>>> test.find('l') # 当元素有多个时,返回最小索引2>>> test.find('a') # 找不到则为-1-1
S.index(sub) —> 返回该元素最小的索引
实际上,该方法与s.find()实现的功能一样,唯一不同的就是当元素不存在时,s.index()方法会报错。这在需要以报错终止程序的测试中就可以用到了。
S.replace(old, new[, count]) —> 替换
>>> test = 'hello python'>>> test.replace('h','H')'Hello pytHon'>>> test'hello python'>>> test.replace('h','H',1)'Hello python'
S.split(sep=None) —> 以sep来分割字符串,并返回列表。sep默认为None,分割默认为空格
>>> test = 'hello python'>>> test.split(' ')['hello', 'python']
S.startswith(prefix[, start[, end]]) —> 判断字符串是否以前缀开始,返回为bool值
- S.endswith(suffix[, start[, end]]) —> 判断字符串是否以尾缀结束,返回为bool值
- S.lower() —> 将字符串全部转为小写
- S.upper() —> 将字符串全部转为大写
- S.strip([chars]) —> 默认去掉字符串左右的空格
- S.isalpha() —> 判断字符串是否全为字母,返回的是bool值
- S.isdigit() —> 判断字符串是否全为数字,返回的是bool值
- S.isalnum() —> 判断字符串是否全为数字或者字母,不存在特殊字符,返回的是bool值
- S.join(iterable) —> 将序列中的元素以指定的字符连接生成一个新的字符串
>>> li = ["hello","wrld"]>>> test = '-'.join(li)>>> print(test)hello-wrld
5. 列表类型
(list 英[lɪst] 美[lɪst])
- 列表简介
- 列表是Python中最基本也是最常用的数据结构之一。列表中的每个元素都被分配一个数字作为索引,用来表示该元素在列表内所排在的位置。第一个元素的索引是0,第二个索引是1,依此类推。
- Python的列表是一个有序可重复的元素集合,可变的序列数据类型,可嵌套、迭代、修改、分片、追加、删除,成员判断。
- 从数据结构角度看,Python的列表是一个可变长度的顺序存储结构,每一个位置存放的都是对象的指针。
例:对于列表 alist = [1, “a”, [11,22], {“k1”:”v1”}],其在内存内的存储方式是这样的:
做简单的列表元素存储方式代码测试:
>>> a = 'a'>>> b = 'b'>>> c = 'c'>>> li = ['a','b','c']>>> id(a)34467432>>> id(li[0])34467432>>> id(b)34465752>>> id(li[1])34465752>>> id(c)30388440>>> id(li[2])30388440
- 列表创建方式
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可
>>> li = [] # 定义一个空的列表 注意 命名不能是list>>> li[]>>> li1 = [1,'wei',0.99] # 任何数据类型都可存储>>> li1[1, 'wei', 0.99]>>> li2 = list()>>> li2[]>>> li3 = list('hello') # list(iterable)>>> li3['h', 'e', 'l', 'l', 'o']
- 列表元素访问
列表从0开始为它的每一个元素顺序创建下标索引,直到总长度减一 。要访问它的某个元素,以方括号加下标值的方式即可。注意要确保索引不越界,一旦访问索引超过范围,会抛出异常。所以,一定要记得最后一个元素的索引是len(list)-1。
>>> lis = ["a", "b", "c"]>>> lis[0]'a'>>> lis[1]'b'>>> lis[2]'c'>>> lis[3]Traceback (most recent call last):File "<pyshell#7>", line 1, in <module>lis[3]IndexError: list index out of range
- 列表元素值修改
```python
li1 = [1,2,3] li1[1] 2
li1[1] = 5 li1 [1, 5, 3]
li1[1:] = [6,7] li1 [1, 6, 7] ```
- 列表元素删除
使用del语句或者remove()、pop()方法删除指定的元素。
>>> li = ['a','b','c']>>> del li[0]>>> li['b', 'c']>>> li = ['a','b','c']>>> li.remove('a')>>> li['b', 'c']>>> li = ['a','b','c']>>> li.pop()'c'>>> li['a', 'b']>>> li = ['a','b','c']>>> li_1 = li.pop(1)>>> li_1'b'>>> li_1 = li.pop(0)>>> li_1'a'>>> li['c']
- 列表其它特定规则
```python
语句 结果 描述
[1, 2, 3] + [4, 5, 6] # [1, 2, 3, 4, 5, 6] 组合两个列表 li1 = [1, 2, 3] li2 = [4, 5, 6] print(li1.add(li2)) # 底层调用了add方法,但是不会改变li1内值 [1, 2, 3, 4, 5, 6]
[‘Hi!’] * 4 # [‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’] 列表的乘法
print(li1.mul(3)) [1, 2, 3, 1, 2, 3, 1, 2, 3]
li1 [1, 2, 3]
3 in li1 #判断元素是否存在于列表中 True
print(li1.contains(1)) #判断li1中有没有1这个元素 True
7. **列表的常用函数**```python# 函数 作用>>> li1 = [1, 2, 3]>>> len(li1) # 返回列表元素个数,也就是获取列表长度 l1.__len__()3>>> max(li1) # 返回列表元素最大值 max(l1) max(1,2,3,4)3>>> min(li1) # 返回列表元素最小值1>>> list('hello') # 将序列转换为列表['h', 'e', 'l', 'l', 'o']>>> s = list((1, "a", "b", 2))>>> s[1, 'a', 'b', 2]>>> max(s) # 不能混合不同类型进行最大最小求值Traceback (most recent call last):File "<pyshell#20>", line 1, in <module>max(s)TypeError: '>' not supported between instances of 'str' and 'int'
列表排序与反转,会直接改变列表内值
>>> li = [1,2,3,4,5,2,1,3,1]>>> li.reverse() # 将列表反转 修改本身 *IN PLACE*>>> li[1, 3, 1, 2, 5, 4, 3, 2, 1]>>> li.sort() # 排序,默认升序 L.sort(key=None, reverse=False)>>> li[1, 1, 1, 2, 2, 3, 3, 4, 5]>>> li.sort(reverse=True) # reverse=True 降序>>> li[5, 4, 3, 3, 2, 2, 1, 1, 1]
切片取值
- 切片指的是对序列进行截取,选取序列中的某一段。语法是: list[start:end:step]
以冒号分割索引,start代表起点索引,end代表结束点索引,step为步长默认为1。省略start表示以0开始,省略end表示到列表的结尾。注意,区间是左闭右开的!
- 如果是负整数下标,则从列表的最后开始往头部查找。例如-1表示最后一个元素,-3表示倒数第三个元素。
切片过程中还可以设置步长,以第二个冒号分割,例如list[3:9:2],表示每隔多少距离取一个元素。
>>> li = ['a','b','c','d','e','f']>>> li[1] # 取'b' 注意:index默认从0开始'b'>>> li[2] # 取'c''c'>>> li[1:3] # 取['b', 'c'] 注意:左闭右开['b', 'c']>>> li[:3] # 取['a', 'b', 'c'] 注意:start不写默认从头开始['a', 'b', 'c']>>> li[2:] # 取['c', 'd', 'e', 'f'] 注意:end不写默认到最后['c', 'd', 'e', 'f']>>> li[:] # 取全部['a', 'b', 'c', 'd', 'e', 'f']>>> li[::2] # 取['a', 'c', 'e'] 注意:步长为2['a', 'c', 'e']>>> li[::-1] # 逆序['f', 'e', 'd', 'c', 'b', 'a']
**
多维列表(嵌套列表)
>>> a = [[1,2,3],[4,5,6],[7,8,9]]>>> a[0][1]2
**
遍历列表元素 ```python a = [1,2,3,4,5,6] for i in a: # 遍历每一个元素本身 print(i)
out
1 2 3 4 5 6
for i in range(len(a)): # 遍历列表的下标,通过下标取值 print(i, a[i])
out
0 1 1 2 2 3 3 4 4 5 5 6
x = 9 if x in a: # 进行是否属于列表成员的判断。该运算速度非常快。 print(“True”) else: print(“False”)
out
False
12. **列表的内置方法**- append(obj) 在列表末尾添加新的对象- count(obj) 统计某个元素在列表中出现的次数- extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)- index(obj) 从列表中找出某个值第一个匹配项的索引位置- insert(index, obj) 将对象插入列表- pop(obj=list[-1]) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值- remove(obj) 移除列表中某个值的第一个匹配项- reverse() 反向列表中元素- sort([func]) 对原列表进行排序- copy() 复制列表- clear() 清空列表,等于del lis[:]注意:其中的类似 append,insert, remove 等方法会修改列表本身,并且返回值为None。```python>>> li = [1,2,3]>>> li.append([3,3])>>> li[1, 2, 3, [3, 3]]>>> li = [1,2,3,[3,3]]>>> li.count(3)1>>> li = [1,2,3]>>> li.extend([4,5])>>> li[1, 2, 3, 4, 5]>>> li = [1,2,3,2,3]>>> li.index(3)2>>> li = ['happy','year']>>> li.insert(1,'new')>>> li['happy', 'new', 'year']>>> li = [1,2,3]>>> li.clear()>>> li[]
拓展:sort()的用法
- 官方定义是
def sort(self, key=None, reverse=False): # real signature unknown; restored from doc “”” L.sort(key=None, reverse=False) -> None — stable sort IN PLACE “”” key用于指定一个函数,即key=函数,即为排序提供一种方法;reverse意为翻转的意思,可以呈现为降序排序等。
- 例如 li = [‘p’,’py’,’pyt’,’pyth’,’pytho’,’python’] ,将列表按照字符长度进行降序排列
- 参数key与lambda匿名函数结合使用,例如 a = [(‘AZ’,’abc’,154),(‘BZ’,’aac’,144), (‘AB’,’abd’,253)]
li = ['p','py','pyt','pyth','pytho','python']li.sort(key=len,reverse=True)print(li)#out['python', 'pytho', 'pyth', 'pyt', 'py', 'p']
a = [('AZ','abc',154),('BZ','aac',144), ('AB','abd',253)]#按照第一个元素进行降序排列print(id(a))a.sort(reverse=True)print(a)print(id(a))#out32161992[('BZ', 'aac', 144), ('AZ', 'abc', 154), ('AB', 'abd', 253)]32161992a = [('AZ','abc',154),('BZ','aac',144), ('AB','abd',253)]#按照第二个元素进行降序排序print(id(a))a.sort(key=lambda i:i[1] ,reverse=True)print(a)print(id(a))#out31965384[('AB', 'abd', 253), ('AZ', 'abc', 154), ('BZ', 'aac', 144)]31965384
拓展:列表的存储模式与访问效率
内存是数据真正存放的地方,是一个存储单元,基本存储单位是字节(bit),一个字节是8位。以32位电脑举例
一个int类型占4个字节,1个字节是8位,存储int(1)就会按照如下进行存储:
点击查看【processon】
那么当我们列表中的元素为不同类型数据结构时,会怎么样呢?
点击查看【processon】
存储的地址会占用4个字节,顺序表的存储结构如下:
点击查看【processon】
这就是列表内存地址不变的原因,是因为列表存储采用的类型为分离式的元素外置存储结构
再探讨一下在列表中添加元素的操作,其时间复杂度的区别:
点击查看【processon】
我们不妨对列表中的几种添加元素的运行效率进行测试,代码如下:
from timeit import Timerdef t1():l=[]for i in range(1000):li=l+[i]def t2():l=[]for i in range(1000):li=l.append(i)def t3():li= [i for i in range(1000)]def t4():li=list(range(1000))def t5():l=[]for i in range(1000):l.insert(0,i)ts1=Timer('t1()','from __main__ import t1')print('add:',ts1.timeit(number=10000))ts2=Timer('t2()','from __main__ import t2')print('append:',ts2.timeit(number=10000))ts3=Timer('t3()','from __main__ import t3')print('list derivation:',ts3.timeit(number=10000))ts4=Timer('t4()','from __main__ import t4')print('list range:',ts4.timeit(number=10000))ts5=Timer('t5()','from __main__ import t5')print('insert:',ts5.timeit(number=10000))#outadd: 1.623764426183277append: 1.3833754859298975 #append的方法耗时1.38秒list derivation: 0.5864754420221825list range: 0.2555692296159324insert: 8.339897477269725 #insert的方法耗时8.34秒
同理去测试pop、remove这两种方法的运行效率
from timeit import Timerdef t1():l=[1,2,34,5]l.pop()def t2():l=[1,2,34,5]l.remove(5)def t3():l=[1,2,34,5]del lts1=Timer('t1()','from __main__ import t1')print('pop:',ts1.timeit(number=1000000))ts2=Timer('t2()','from __main__ import t2')print('remove:',ts2.timeit(number=1000000))ts3=Timer('t3()','from __main__ import t3')print('del:',ts3.timeit(number=1000000))#outpop: 0.4461612876740691 #pop方法耗时0.38秒remove: 0.4898481257117155 #remove方法耗时0.47秒del: 0.2638907233349873 #del方法耗时0.26秒
在Python中,列表采用的存储策略是:
- 建立空表或者8元素以内的列表时,系统分配一块能容纳8元素的存储区;
- 在执行列表元素新增操作时,如元素存储区满了,就换4倍存储区;
- 如果表元素>>50000,则改变策略采用指数加一倍的方式扩容存储区;
- 这样的存储策略的目的是避免出现多空闲的存储位置。
拓展:如何实现LRU的缓存淘汰算法呢?
缓存是高速读取数据的技术,在例如CPU缓存、数据库缓存、浏览器缓存等存在非常广泛应用。
当缓存将满时,需要清理出去次要数据时,就需要相应的策略来完成,常见的有:
- FIFO先进先出策略(First In First Out)
- LFU最少使用策略(Least Frequently Used)
- LRU最近最少使用策略(Least Recently Used)
好比我们整理内务时,先是把很早以前的现在用不上的清除出去,然后到基本上用不上的清除掉,最后把最近比较少用的考虑清除出去。
元组类型
(tuple 英 [tʌpl] 美 [tʌpl])元组基本属性
用圆括号括起来的是元组。元组也是序列结构,但是是一种不可变的序列数据类型,你可以简单的理解为内容不可变的列表。除了在内部元素不可修改的区别外,元组和列表的用法差不多。如len()/max()/min()/tuple()等
元组和列表都采用了顺序表的实现技术。不同之处在于:
列表为可变线性表,可增删元素,并且保序,可下标访问与更新,内存地址保持不变,采用分离式的动态存储顺序表技术来实现;时间复杂度为O(1);
[x] 列表中还有list.reverse()与list.sort() 但是元组没有。元组要实现反转与排序使用reversed(),sorted()
reversed()内置函数返回的是一个内存地址,要使用tuple()函数将其调用出来成为元组呈现。
>>> tu1 = (1,2,3,4,5,5,5,6)>>> reversed(tu1)<reversed object at 0x0000000002E36C88>>>> tuple(reversed(tu1))(6, 5, 5, 5, 4, 3, 2, 1)>>> tu = (1,-1,2,3,5,2,0)>>> sorted(tu)[-1, 0, 1, 2, 2, 3, 5]
- 元组操作注意事项
- 元组不允许增删元素。若想改变该元组,就只能重新开辟一块内存,创建新的元组
- 元组只保证它的一级子元素不可变,但是对于嵌套的元素内部,不保证不可变
```python
tu_test = (1,2,[‘WEI’,3,0]) tu_test[2][0] = ‘wei’ tu_test (1, 2, [‘wei’, 3, 0])
tu_test = (1,2,(‘wei’,3,0)) tu_test[2][0] = ‘WEI’ Traceback (most recent call last): File “
“, line 1, in tu_test[2][0] = ‘WEI’ TypeError: ‘tuple’ object does not support item assignment ```
- 不允许删除某个元素(但可以删除整个元组)
- 所有会对元组内部元素发生修改的方法都不能使用。例如,元组没有remove,append,pop等方法
7. 字典类型
(dictionary 英 [ˈdɪkʃənri] 美 [ˈdɪkʃəneri] )
- 功能简介
字典可精确描述为不定长、可变、无序、散列的集合类型,可变的序列数据类型
- Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,查取与插入速度快。
- 它是无序的,包含的元素个数不限,值的类型也可以是其它任何数据类型!
- 字典的key必须是不可变的对象,例如整数、字符串、bytes和元组,但使用最多的还是字符串。 列表、字典、集合等就不可以作为key。同时,同一个字典内的key必须是唯一的,但值则不必。
- 字典的每个键值对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中。
d = {key1 : value1, key2 : value2 }
- 字典创建方式
```python
dic = {} dic {} type(dic)
dict() {}
dic1 = {‘name’:’amy’,’age’:’18’} type(dic1)
dic2 = dict(name=”amy”,age=’18’) type(dic2)
dic3 = dict([(‘name’,’amy’),(‘age’,’18’)]) type(dic3)
dic1 == dic2 == dic3 # ==比较数值 True ``` **
- 字典访问
字典是集合类型,不是序列类型,因此没有索引下标的概念,更没有切片的说法。但是与list类似,字典采用把相应的键放入方括号内获取对应值的方式取值。可以通过dic.keys()以及dic.values()访问键值与key值。
>>> dic_1 = {'name':'wei','age':18}>>> dic_1['age']18>>> type(dic_1['age'])<class 'int'>>>> dic_1['gender']Traceback (most recent call last):File "<pyshell#73>", line 1, in <module>dic_1['gender']KeyError: 'gender'
- 字典元素增改
增加就是往字典插入新的键值对,修改就是给原有的键赋予新的值。由于一个key只能对应一个值,所以,多次对一个key赋值,后面的值会把前面的值冲掉。
>>> dic_1 = {'name':'wei','age':18}>>> dic_1['gender'] = "male" # 增加key值为"gender",value值为"female"的元素>>> dic_1{'name': 'wei', 'age': 18, 'gender': 'male'}>>> dic_1['gender'] = 'male' # 当有该key:value值时,取出来重新赋值则进行了修改>>> dic_1{'name': 'wei', 'age': 18, 'gender': 'male'}
**
- 删除字典元素、清空字典和删除字典
使用del关键字删除字典元素或者字典本身,使用字典的clear()方法清空字典。注意参数为key,不能是value值。
>>> dic_1 = {'name': 'wei', 'age': 18, 'gender': 'male'}>>> del dic_1['wei']Traceback (most recent call last):File "<pyshell#78>", line 1, in <module>del dic_1['wei']KeyError: 'wei'>>> del dic_1['name']>>> dic_1{'age': 18, 'gender': 'male'}>>> dic_1.clear()>>> dic_1{}>>> del dic_1>>> dic_1Traceback (most recent call last):File "<pyshell#84>", line 1, in <module>dic_1NameError: name 'dic_1' is not defined
**
- 字典的方法
- get(key) 返回指定键的值,如果值不在字典中,则返回default值
- items() 以列表返回可遍历的(键, 值) 元组对
- keys() 以列表返回字典所有的键
- values() 以列表返回字典所有的值
```python
dic_1 = {‘name’: ‘wei’, ‘age’: 18, ‘gender’: ‘male’} dic_1.get(‘age’) 18 dic_1.get(‘school’)
dic_1.items() dict_items([(‘name’, ‘wei’), (‘age’, 18), (‘gender’, ‘male’)])
for i,j in dic_1.items(): print(i,j)
name wei age 18 gender male
dic_1.keys() dict_keys([‘name’, ‘age’, ‘gender’]) dic_1.values() dict_values([‘wei’, 18, ‘male’]) ``` **
拓展:map()函数
- 功能:根据提供的函数对指定序列做映射
**
- 通过map函数,将指定序列中的元素进行一一映射,从而可以生成新的字典
>>> a = list('1234')>>> type(a)<class 'list'>>>> print(map(int,a))<map object at 0x0000000002E24FD0>>>> print(list(map(int,a)))[1, 2, 3, 4]>>> a['1', '2', '3', '4']
>>> li1 = ["name","age","gender"]>>> li2 = ["wei",18,'male']>>> def get(i,j):return (i,j)>>> print(dict(list(map(get,li1,li2)))){'name': 'wei', 'age': 18, 'gender': 'male'}
拓展:zip()函数
- 功能:zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表对象
- 例如通过zip()函数实现上一题目中的一一映射并输出为字典
>>> li1 = ["name","age","gender"]>>> li2 = ["wei",18,'male']>>> print(dict(zip(li1,li2))){'name': 'wei', 'age': 18, 'gender': 'male'}
拓展:filter()函数
filter函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。filter(function or None, iterable) —> filter object
- function为自定义函数
- iterable为可迭代的对象
- 返回值为filter对象
练习
- 返回1-10的奇数列表。
def t(n):return n % 2 == 1li = list(filter(t,range(1,10)))print(li)#out[1, 3, 5, 7, 9]
li = []for i in range(1,11,2): # for i in range(1,11)li.append(i) # if i%2== 1:print(li) # li.append(i)#out # print(li)[1, 3, 5, 7, 9]
8. bytes类型
- 基本介绍
在Python3以后,字符串和bytes类型彻底分开了。字符串是以字符为单位进行处理的,bytes类型是以字节为单位处理的。bytes数据类型在所有的操作和使用甚至内置方法上和字符串数据类型基本一样,也是不可变的序列对象。Python3中,bytes通常用于网络数据传输、二进制图片和文件的保存等等。
- bytes创建
可以通过调用bytes()生成bytes实例,其值形式为 b’xxxxx’,对于同一个字符串如果采用不同的编码方式生成bytes对象,就会形成不同的值。
>>> a = b'hello'>>> type(a)<class 'bytes'>>>> b = bytes('hello',encoding='utf8')>>> type(b)<class 'bytes'>
- bytes类型常用转换
那在实际应用中,我们通常会将bytes类型与str类型做转换。
>>> d = b'world'>>> d.decode() #字节转换为字符串'world'>>> type(d)<class 'bytes'>>>> e = 'world'>>> e.encode() #字符串转换为字节b'world'>>> type(e)<class 'str'>
9. 集合(set)
- 基本属性
set集合是一个无序不重复元素的集,可变的序列数据类型,基本功能包括关系测试和消除重复元素。集合数据类型的核心在于自动去重。
- 创建集合
集合使用大括号({})框定元素,并以逗号进行分隔。但是注意:如果要创建一个空集合,必须用 set() 而不是 {} ,因为后者创建的是一个空字典。
>>> s = {1,2,3}>>> s{1, 2, 3}>>> type(s)<class 'set'>>>> s = {} # 注意,空的{}会默认为字典>>> type(s)<class 'dict'>
集合还可以使用set()函数来创建。使用方法如下:
- set() -> new empty set object(创建空集合)
- set(iterable) -> new set object(创建集合),传入的值必须是可迭代对象
```python
s = set() # 创建空集合 s set() type(s)
s = set([1,2,3,1,2,3,4]) # 创建集合,去重 s {1, 2, 3, 4} s1 = set(“hello world”) # 创建集合,去重 s1 {‘h’, ‘d’, ‘o’, ‘ ‘, ‘e’, ‘l’, ‘r’, ‘w’} s2 = set(123) # 注意,需要传入可迭代的对象,而int类型的123并不是,所以报错 Traceback (most recent call last): File “
“, line 1, in TypeError: ‘int’ object is not iterable ```
- 添加集合元素
通过add(key)方法可以添加元素到set中,可以重复添加,但依然遵循去重的原则,添加元素需要为不可变对象
>>> s = {1,2,3,4,5,6}>>> s.add({1,2})Traceback (most recent call last):File "<pyshell#2>", line 1, in <module>s.add({1,2})TypeError: unhashable type: 'set'>>> s.add('1')>>> s{1, 2, 3, 4, 5, 6, '1'}>>> s.add(1)>>> s{1, 2, 3, 4, 5, 6, '1'}>>> s.add((1,2,3,4,7,9,10))>>> s{1, 2, 3, 4, 5, 6, (1, 2, 3, 4, 7, 9, 10), '1'}
- 更新集合元素
可以通过update()方法,将另一个对象更新到已有的集合中,这一过程同样会进行去重。添加元素需要为不可变对象
>>> s = set([1,2,3,4,5])>>> s.update("hello") # 将hello拆开放入集合>>> s{1, 2, 3, 4, 5, 'h', 'o', 'e', 'l'}>>> s.update("hello") # 仍然去重>>> s{1, 2, 3, 4, 5, 'h', 'o', 'e', 'l'}
- 删除与访问集合元素
- 通过remove(key)方法删除指定元素,或者使用pop()方法。注意,集合的pop方法不能通过索引删除元素。
- 集合不能取出某个元素,因为集合既不支持下标索引也不支持字典那样的通过键值对获取。
```python
s = {1, 2, 3, 4, 5, ‘h’, ‘o’, ‘e’, ‘l’} s.remove(1) # 删除该元素 s {2, 3, 4, 5, ‘h’, ‘o’, ‘e’, ‘l’} s.remove(‘h’) # 删除该元素 s {2, 3, 4, 5, ‘o’, ‘e’, ‘l’} s.remove(‘www’) # 删除不存在的元素则报错 Traceback (most recent call last): File “
“, line 1, in KeyError: ‘www’
s1 = set(“hello world”) s1.pop() ‘h’ s1.pop() ‘d’ s1.pop() # 注意是随机删除 ‘o’ s1.pop(1) # 不能通过索引删除,因为本身无序 Traceback (most recent call last): File “
“, line 1, in TypeError: pop() takes no arguments (1 given) s1 {‘ ‘, ‘e’, ‘l’, ‘r’, ‘w’} s1[1] Traceback (most recent call last): File “
“, line 1, in TypeError: ‘set’ object does not support indexing ``` 集合数据类型属于Python内置的数据类型,在很多书籍中甚至都看不到一点介绍。其实,集合是一种非常有用的数据结构,它的去重和集合运算是其它内置类型都不具备的,在很多场合有着非常重要的作用,比如网络爬虫。
拓展:集合方法
- 交集:s1 = {‘yellow’, ‘red’, ‘blue’, ‘green’, ‘black’} s2 = {‘red’, ‘brown’} ,求两个集合的交集
s1 = {'yellow', 'red', 'blue', 'green', 'black'}s2 = {'red', 'brown'}print(f'{s1},数据类型为{type(s1)}')print(f'{s2},数据类型为{type(s2)}')print(f'两个集合的交集为{s1.intersection(s2)},数据类型为{type(s1.intersection(s2))}')#out{'green', 'red', 'blue', 'yellow', 'black'},数据类型为<class 'set'>{'brown', 'red'},数据类型为<class 'set'>两个集合的交集为{'red'},数据类型为<class 'set'>
[x] 差集:s1 = {‘yellow’, ‘red’, ‘blue’, ‘green’, ‘black’} s2 = {‘red’, ‘brown’} ,求两个集合的差集
[ ]
s1 = {'yellow', 'red', 'blue', 'green', 'black'}s2 = {'red', 'brown'}print(f'{s1},数据类型为{type(s1)}')print(f'{s2},数据类型为{type(s2)}')print(f'两个集合的差集为{s1.difference(s2)},数据类型为{type(s1.difference(s2))}')#out{'red', 'black', 'green', 'blue', 'yellow'},数据类型为<class 'set'>{'red', 'brown'},数据类型为<class 'set'>两个集合的差集为{'green', 'black', 'blue', 'yellow'},数据类型为<class 'set'>
10. 类型转换函数
int(x [,base ]) 将x转换为一个整数
long(x [,base ]) 将x转换为一个长整数
float(x ) 将x转换到一个浮点数
complex(real [,imag ]) 创建一个复数
str(x ) 将对象 x 转换为字符串
repr(x ) 将对象 x 转换为表达式字符串
eval(str ) 用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s ) 将序列 s 转换为一个元组
list(s ) 将序列 s 转换为一个列表
chr(x ) 将一个整数转换为一个字符
unichr(x ) 将一个整数转换为Unicode字符
ord(x ) 将一个字符转换为它的整数值
hex(x ) 将一个整数转换为一个十六进制字符串
oct(x ) 将一个整数转换为一个八进制字符串
练习
- lis1 =[‘name’,’author’,’introduce’] lis2 =[‘NORWEGIAN WOOD’,‘Haruki Murakami’,‘balalalalal…’],将 lis1 与 lis2 以键值对的形式呈现
lis1 =['name','author','introduce']lis2 =['NORWEGIAN WOOD','Haruki Murakami','balalalalal...']def get(i,j):return(i,j)print(dict(list(map(get,lis1,lis2)))) #1使用map函数进行转换print(dict(zip(lis1,lis2))) #2使用zip函数更直观简洁
- wei_inf = {‘name’:’wei’,‘addr’:’anhui’,‘weight’:65} 获取 amy_info 的 key,value值
>>> wei_inf = {'name':'wei','addr':'anhui','weight':65}>>> print(wei_inf.values())dict_values(['wei', 'anhui', 65])>>> print(wei_inf.keys())dict_keys(['name', 'addr', 'weight'])
- 生成了 N 个 1~1000 之间的随机整数(N<=1000),N 是用户输入的, 对于其中重复的数字,只保留一个,把其余相同的数字去掉,然后再把这些数从小到大排序。(注意:此处需要使用随机整数。可了解 random 模块具体方法、for 循环、range()函数等结合使用,作为预习)
import randomn = int(input('请输入测试数据: '))test_1 = set()for i in range(n):test_1.add(random.randint(1,1000))print(sorted(test_1))#out请输入测试数据: 5[356, 449, 775, 804, 961]
- 字节如何转字符串,字符串如何转字节
>>> d = b'world'>>> d.decode() #字节转换为字符串'world'>>> type(d)<class 'bytes'>>>> e = 'world'>>> e.encode() #字符串转换为字节b'world'>>> type(e)<class 'str'>
- 用代码结合文字表达可变与不可变数据类型差别
#数值、字符串、元组、字节都是不可变数据类型,改变它的元素值,其本质是改变了数据内存id#列表list[]、集合set{}、字典dic{,}是可变数据类型,改变了它的元素值,而不会改变数据内存id>>> a = 'hellow'>>> id(a)48923792 #内存地址A>>> id('hellow')48923792 #内存地址A>>> a = 'type'>>> id(a)1370184 #内存地址B>>> id('type')1370184 #内存地址B>>> li = [1,2,3,4,5]>>> id(li) #内存地址A49089736>>> li.append(3)>>> li[1, 2, 3, 4, 5, 3]>>> id(li)49089736 #内存地址A>>> tu = (1,2,3,4,5)>>> type(tu)<class 'tuple'>>>> id(tu)48511640 #内存地址A>>> sorted(tu)[1, 2, 3, 4, 5]>>> tu(1, 2, 3, 4, 5)>>> tuple(reversed(tu))(5, 4, 3, 2, 1)>>> tu(1, 2, 3, 4, 5)>>> id(tuple(reversed(tu)))48511552 #内存地址B
二、运算符
1. 概念与类型
以1 + 2为例,1和2被称为操作数,”+” 称为运算符。Python语言支持以下类型的运算符:
- 算术元运算符
- 比较(关系)运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
- 三目运算符
2. 算数元运算符

- / 计算结果是浮点数,即使两个数都是整数,结果也是浮点数
```python
9/3
3.0
10/3 3.3333333333333335 ```
10/3不应该是3.3333333333333333333333无限循环吗?那实际上是因为计算机内存与cpu的有穷性导致结果为3.3333333333333335。
- // 只取整数部分,余数被抛弃,向下取整
```python
10//3
3
-10//3 -4 # 向下取整 ```
- % 余数运算,可以得到两个整数相除的余数
```python
10%3
1
-10%3 2 # 向下取整 ```
如果想同时得到商和余数,可以用divmod()这个方法,该方法的返回值是tuple (x//y, x%y)
>>> divmod(10,3)(3,1)>>> divmod(-10,3)(-4, 2)
- 因为浮点数精度的问题,Python计算中会出现与常规认知上面的偏差,这个时候需要导入decimal模块
```python
0.1+0.1+0.1-0.3 5.551115123125783e-17
from decimal import Decimal Decimal(‘0.1’)+Decimal(‘0.1’)+Decimal(‘0.1’)-Decimal(‘0.3’) Decimal(‘0.0’) ```
pow函数:里面可以有两个或三个参数,它们的意义是完全不同的。
>>> pow(2,3)8>>> pow(2,3,4)0>>>
3. 比较运算符

- 比较运算符返回值为bool值
- ==比较数值(int类型与str类型不能直接比较)
- != 与 <> 均为不等于,python3中(python3中<>已弃用)
- 字符串与字符串之间是比较ASCII值
4. 赋值运算符

- Python不支持a++语法
- 注意 += 不能拆开写 + =
5. 位运算符

位运算符是把数字看作二进制来进行计算的。Python中的位运算法则如下:
a = 0011 1100b = 0000 1101-----------------a&b = 0000 1100a|b = 0011 1101a^b = 0011 0001~a = 1100 0011
6. 逻辑运算符
Python语言支持逻辑运算符,但是没有其它语言中的&&和||语法,取而代之的是更加人性化的英文单词and or not(全部都是小写字母)。
7. 成员运算符
in 与 not in是Python独有的运算符(全部都是小写字母),用于判断对象是否某个集合的元素之一,非常好用,并且运行速度很快。返回的结果是布尔值类型的True或者False。
练习
- 判断随机数据a是否在随机列表list1中
import randomlist1 = [i for i in range(0,100) if i < random.randint(0,100)]a = random.randint(0,100)if a in list1:print(f'随机数据{a}在列表中\n',list1)else:print(f'随机数据{a}不在列表中\n',list1)
8. 身份运算符
这也是Python的特色语法(全部都是小写字母)。
注意is与比较运算符==的区别,两者有根本上的区别,切记不可混用:
is用于判断两个变量的引用是否为同一个对象(可使用id()查看),而==用于判断变量引用的对象的值是否相等!
>>> a = [1,2,3]>>> b = [1,2,3]>>> a is bFalse>>> a == bTrue>>> id(a) # 可通过id()查看内存地址48825800>>> id(b)48825992
9. 三目运算符
python中的三目运算符表示方法:True_statements if expression else False_statements
import randomlist1 = [i for i in range(0,100) if i < random.randint(0,100)]a = random.randint(0,100)print(f'随机数据{a}在列表{list1}中\n') if a in list1 else print(f'随机数据{a}不在列表{list1}中\n')
10. 运算符优先级
下表列出了从最高到最低优先级的所有运算符。优先级高的运算符优先计算或处理,同级别的按从左往右的顺序计算(赋值运算符除外,它是按从右往左的顺序)
其它常用的部分函数: abs(number) 返回数字的绝对值 cmath.sqrt(number) 返回平方根,也可以应用于负数 float(object) 把字符串和数字转换为浮点数 help() 提供交互式帮助 input(prompt) 获取用户输入 int(object) 把字符串和数字转换为整数 math.ceil(number) 返回数的上入整数,返回值的类型为浮点数 math.floor(number) 返回数的下舍整数,返回值的类型为浮点数 math.sqrt(number) 返回平方根不适用于负数 pow(x,y[.z]) 返回X的y次幂(有z则对z取模) repr(object) 返回值的字符串标示形式 round(number[.ndigits]) 根据给定的精度对数字进行四舍五入 str(object) 把值转换为字符串
练习
- 如何判断”bob”是否在[“bob”,”tony”,”Lisa”,”Steven”]里面? 如果在则输出’bob 在逻辑大家庭’ 否则输出’bob 不在…好难过’
print(f'bob 在逻辑大家庭' if 'bob' in ["bob","tony","Lisa","Steven"] else 'bob 不在...好难过')
- ‘ax’<’xa’ 为 True 还是 False?
>>> 'ax' < 'xa'True #字符串比较的是ASCII码值
- 以下程序如果输入 666 执行那个语句?为什么?
>>> temp = input('请输入:')请输入:666>>> if temp == 'Yes' or 'yes': # == 比较运算符高于 or逻辑运算符print('if执行了') #比较运算符的返回值是bool值, '666' == 'Yes' 返回值为Falseelse: # or逻辑运算符,False or 'yes' 的逻辑运算返回的是非0值'yes'print('else执行了') #最终的判断执行了if语句,所以会有最终的输出结果产生if执行了
- is 与==的区别是什么?
is用于判断两个变量的引用是否为同一个对象(可使用id()查看),而==用于判断变量引用的对象的值是否相等!
- 用户输入 a,b。当 a 与 b 都不为 0 时,则输出 a 与 b 做商;否则输出 a 与 b 的乘积。使用三目运算符输出 a,b 较大的数
from decimal import Decimala = float(input('请输入a值: '))b = float(input('请输入b值: '))print(f'返回值为:{round(Decimal(a/b),2)}' if a != 0 and b != 0 else f'返回值为:{round(Decimal(a)*Decimal(b),2)}')print(f'输入的值中,较大值为:a= {a}' if a > b else f'输入的值中,较大值为:b= {b}')
- ’1’+’2’的结果是多少?
>>> '1'+'2' #字符串的 + 运算是拼接'12'
- 当输入 y 或 Y 提示进入卸载,当输入 n 或 N 提示退出程序,输入其它 则提示输入不在选项范围之内(应用到 str.upper()或 str.lower())
test = input('是否需要卸载:(Y/N) ')if test.upper() == 'Y':print(f'进入卸载')elif test.upper() == 'N':print(f'退出程序')else:print('输入不在选项范围内')
