数字类型在Pyhton中非常常见,经常用于数字之间的运算、大小比较、条件判断等等。数字类型包括:整型、浮点型、复数型、布尔型。其中布尔型属于特殊的数字类型。
整型,在Python中用 int 来表示,也就是integer。通俗来说就是我们的所讲的整数,包括正整数和负整数。整型的表现形式如 6,100,-135 等等。还记得type方法么?可以通过type来查看数据类型。
print(type(1)) print(type(-23))
在Python2.x中,整型还被分为整型 int 和 长整型 long。整型根据计算机的位数,有取值范围限制。超过整型的取值范围后,解释器会自动的将整型转换成长整型。而长整型理论上是没有限制的。
在32位系统中,整型的范围在-2**31~2**31-1,即-2147483648~2147483647
在64位系统中,整型的范围在-2**63~2**63-1,即-9223372036854775808~9223372036854775807
而Python3.x中,整形与长整形进行了无缝结合,也就是现在的整形,长度在理论上来说是不受限制的,但是由于计算机内存的限制,实际上是不能无限大的。
整型 int 还有其他的用处,看下面代码:
>>> int(1.5) # 浮点数转整型 1 >>> int(‘123‘) # 字符串转整型 123 >>> int(‘abc‘) # 只支持数字型字符串 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: ‘abc‘
在 int 后面加括号,可以将括号内的对象转换成整型,传入的对象可以是整数、浮点数、布尔型、整数型字符串等。如果传入浮点数,直接去尾留整,而不是四舍五入。传入的字符串必须是整数型字符串。
Python中的浮点数可以近似理解为数学中的小数,带着小数点的数就是浮点数。浮点数还有不同的表示形式:正常形式(带小数点)和科学记数法。浮点数很大和很小的情况下解释器会自动转换成科学记数法的表现形式。而在运算中,整数和浮点数进行运算结果也是为浮点数。
>>> 1000000000000000000.5 1e+18 >>> 0.0000000000000000045 4.5e-18
Python默认的是17位精度,也就是小数点后16位,尽管有16位,但是这个精确度却是越往后越不准的。
首先,这个问题不是只存在在python中,其他语言也有同样的问题
其次,小数不精准是因为在转换成二进制的过程中会出现无限循环的情况,在约省的时候就会出现偏差。
>>> float(1) 1.0 >>> float(‘12‘) 12.0 >>> float(‘1.2‘) 1.2
浮点也有与整型类似的方法,可以将传入的对象转换成浮点型。可以传入整型、浮点型、布尔型、数字型字符串等。
Python中的复数就是我们数学中接触过的复数,由两部分组成:实数部分和虚数部分,表现形式为: a+bj (数学中的虚数单位用 i 表示,而Python中用 j )。其中a与b都是实数,j为虚数单位(-1的平方根),当虚数部分的系数b为零时,这个复数就是实数;当虚数部分的系数b不为零时,这个复数就是虚数。复数通常是用不到的,但是在工程领域使用较多。
>>> type(1+2j) <class ‘complex‘> >>> complex(1.2) (1.2+0j) >>> complex(‘5‘) (5+0j)
复数的方法可以将传入的整型、浮点型、数字型字符串等对象转换为复数形式。
布尔类型属于特殊的数字数据类型。布尔型只有两种值:True 对应数字1;False 对应数字0。为什么说布尔型是特殊的数字类型呢?因为它们可以互相运算:
>>> True + True 2 >>> True + False 1 >>> True - False 1
虽然可以相互运算,但是没人会真的去用 True 代表1,False 代表0来进行计算,一般都是反过来,通过传入的一些数据转换成布尔值来进行条件判断的。传入的数据如果成立或者非空,即为 True,如果传入的数据不成立、为空、数字0或者为None,即为 False。这就使得进行判断时,判断的条件写法可以更丰富。
>>> bool(1 > 2) False >>> bool(‘‘) False >>> bool(None) False >>> bool(0) False >>> bool(‘1‘) True
以下通用,假设现有两个变量,a = 10,b = 20。
10: 01010 &20: 10100 0 00000 |
10: 01010 |20: 10100 30 11110 |
10: 01010 ^20: 10100 30 11110 |
10>>1: 1010 5 0101 |
10<<1: 01010 20 10100 |
上一篇已经简单介绍过了字符串,字符串也叫文本,引号内的一切东西都叫字符串。当然字符串还有很多功能和使用方法。
在字符串的前面加上英文字母r,即表示这段字符串是原始字符串。原始字符串主要使用在用字符串描述文件路径,防止转义字符生效,比方说\n、\t、\v等等。
>>> print(‘c\ns‘) # \n表示换行符 c s >>> print(r‘c\ns‘) # 变成原始字符串 c\ns
说字符串的格式化你可能不太懂,但是看了下面的例子你就能明白了。这里主要介绍两种字符串的格式化方法:format和格式化操作符%。
print(‘{a}{b}‘.format(a=‘你‘,b=‘好‘)) # a,b是关键字参数 print(‘{0}{1}‘.format(‘你‘,‘好‘)) # 0,1是位置参数 # 输出均为 你好
format方法可以接收两种参数,位置参数和关键字参数。位置参数就是用整型表示,0表示第一位,依次后推;而关键字参数则通过相同类似变量赋值的方法来表示。位置参数和关键字参数何以混搭,但是位置参数一定要放在关键字参数之前,否则会报错。
string = ‘name:%s‘ # 定义一个字符串,需要格式化的位置写入格式化操作符 print(string%‘jack‘) # % 后面写入要格式化的内容
格式化操作符不止有%s
下面来进行一个实例演示,现在我想打印出一个个人信息,包含姓名、年龄、性别、工作。要求信息需要用户输入(input方法)。
name = input(‘name>>‘) age = input(‘age>>‘) sex = input(‘sex>>‘) job = input(‘job>>‘) info1 = ‘‘‘---个人信息--- 姓名:{name} 年龄:{age} 性别:{sex} 工作:{job}‘‘‘.format(name=name,age=age,sex=sex,job=job) print(info1) info2 = ‘‘‘---个人信息--- 姓名:%s 年龄:%s 性别:%s 工作:%s‘‘‘ % (name,age,sex,job) print(info2)
字符串还可通过索引值来访问内部和分片拷贝。
想要访问字符串其中的一个字符可以通过 <[索引值]> 这样的方法来实现,索引值从0开始,0表示字符串里的第一个字符,-1表示最后一个
分片则可以取到字符串内的多个字符 <[start:stop:step]>,省略开始索引表示从头开始取,省略结束索引表示一直取到结尾,都省略表示从头到尾拷贝,步长默认为1。
string = ‘abcdefghijk‘ print(string[0],string[4],string[7],string[-1]) # a e h k print(string[1:10]) # bcdefghij 去尾不去头 print(string[:3]) # abc 不写开始索引表示从头开始 print(string[7:]) # hijk 不写结束索引表示直到结尾 print(string[::2]) # acegik 步长不写默认为1 写入后可以改变步长
这里的分片操作是对字符串的一种拷贝,并不修改原字符串。
列表在Python中用 list 表示。列表就是用来储存一堆数据、参数、变量等等的“组”。列表里可以储存数字、字符串、元组、变量,甚至还可以存列表,列表里的每个元素都可通过下标索引找到,按照从左到右的顺序,下标从0开始向下排列。列表由[ ]表示,里面的各个元素用逗号隔开,例如:[‘a’,1,,[3,4],3.14]。列表非常灵活,可以任意的添加元素、修改元素和删除元素。
列表主要是依靠索引值来获取列表内元素的。我们知道索引值从0开始,也就是列表内第一个元素的索引值为0,如果不知道最后一个元素的索引值,可以直接用-1表示。倒数第二个可以用-2表示。那列表中的元素如何获取呢?
l = [1,2,3,4,5,6,7,8,9] print(l[0],l[2],l[-1]) # 通过[索引值]的方式获取
列表和字符串一样,可以进行切片操作,或许你对字符串的切片还有些迷糊,但是列表的很多操作都是需要用到索引值的,所以,对于列表的切片你应该看得更清楚。列表的切片与字符串一模一样,这里就不详细讲了,直接上代码。
l = [1,2,3,4,5,6,7,8,9] print(l[2:6]) # [3,4,5,6] print(l[:3]) # [1,2,3] print(l[6:]) # [7,8,9] print(l[:]) # [1,2,3,4,5,6,7,8,9] print(l[1:7:2]) # [2,4,6]
创建列表有两种方式:通过列表的表示形式直接写出一个列表,或者用list()方法来创建。
# 创建空列表 list1 = [] list2 = list() print(type(list1),type(list2)) # 创建有元素的列表 list3 = [‘a‘,‘b‘,‘c‘] list4 = list(‘abc‘) print(list3,list4)
向一个列表中添加元素,有三种方法:append(object)、extend(iterable)、insert(index, object)。
l = [1,2,3] l.append(4) # 只能在列表末尾添加元素,一次只能添加一个元素 l.extend([5,6]) # 只能在列表末尾添加元素,可以添加多个 l.insert(0,0) # 将新元素插入到索引值对应的元素的前面
列表的灵活之处除了可以存储任意的数据类型任意个,也可以随便修改里面的元素。首先获取到列表中的某个元素,通过赋值语句来进行修改。
list1 = [1,2,4] list1[2] = 3 print(list1) list2 = [1,[0,2]] list2[1][0] = 1 print(list2)
列表可以进行删除操作,删除其中任意一个元素甚至删除整个列表。删除的方法有remove(value)、del、pop(index=-1)、clear()。
l = [1,2,3,4,5,6,7,8] l.remove(1) # 括号内传入想要删除的元素,如果元素不存在则报错 l.pop() # 括号内传入索引值,索引值超范围报错,不传入表示默认移除最后一个元素 del l[2] # 通过del语句删除列表中的元素, del l 可以直接删除 l 这个列表变量 l.clear() # 清空列表内的所有元素
count(value, /),用于计算输入值在列表中的出现的次数。
>>> l = [1,2,4,2,3,2] >>> l.count(2) 3
index(value, start=0, stop=9223372036854775807, /),用于返回输入值在列表中的索引值,从左至右依次寻找。如果有多个相同的元素,返回找到的第一个元素的索引值,如果不在列表中则会报错,可以设置起始结束位置,32位的机器结束位置最大为2**31-1,64位机器结束位置最大2**63-1。
>>> l = [1,2,3,1] >>> l.index(1) 0 >>> l.index(1,1) 3
reverse(),用于将目标列表中所有元素倒序,但只是顺序发生变化。
sort(*, key=None, reverse=False),func和key参数是用来设置排序的算法和关键字,默认使用归并排序,这里先不多解释,reverse参数设置列表的正序和倒序,默认为False即正序,当设置成True即倒序。sort()方法是先按照设定的方法排序,在根据reverse的布尔值决定是否倒序。但是,列表中的各元素的数据类型应保持一致。
>>> l = [1,2,3,4] >>> l.reverse() >>> l [4, 3, 2, 1] >>> l.sort() >>> l [1, 2, 3, 4]
copy(),返回一个浅copy的列表。两个列表的内存地址不一样。
>>> l = [1,2,3] >>> l1 = l.copy() >>> l1 [1, 2, 3]
深浅copy
列表的copy方法是浅copy,那么一定有深copy。那这两者有什么区别呢?还记得上一篇讲到变量名的单一指向关系么?两个变量名同时指向一个对象,当对其中一个变量重新赋值时,并不会改变另一个变量。这是因为赋值操作相当于重新创建一个变量,之前的指向关系就会消失,而另一个变量由于指向关系不变,并不受影响。这个规则当然也适用于列表,因为列表也是变量嘛,但是列表还有些不同。
list1 = [1,2,3] list2 = list1 list3 = list1.copy() list4 = list1[:] # 与copy作用相同 list1 = [3,2,1] # 对list1重新赋值 print(list2,list3,list4) # 输出结果 [1, 2, 3] [1, 2, 3] [1, 2, 3] 可以发现确实满足变量的单一指向性 #那么现在换一种方式 list1 = [1,2,3] list2 = list1 list3 = list1.copy() list4 = list1[:] list1[0] = 0 # 修改list1中的元素 print(list2,list3,list4) # 输出结果 [0, 2, 3] [1, 2, 3] [1, 2, 3]对list1重新赋值,一切都按我们想的。但是如果是对list1内的元素进行修改,list2却发生变化。这是由于列表[1,2,3]本身会占用一块内存空间,而列表内的每个元素都有单独的内存地址。当修改list1内的元素时,list2仅仅指向列表的内存地址,却与列表内元素的内存地址不相干,所以也跟着改了。但是copy和分片操作同时也拷贝了列表内元素的内存地址,所以并未修改。而这和深浅copy有什么关系呢?别急,往下看。
list1 = [[1,2],3] list2 = list1 list3 = list1.copy() list4 = list1[:] list1[0][0] = 0 print(list2,list3,list4) # 输出结果 [[0, 2], 3], [[0, 2], 3], [[0, 2], 3] 为什么又全改了呢?在list1内加入一个子列表,修改子列表内的元素,发现又不一样了,连copy和切片也一起改了,这就是我们所说的浅copy了。浅copy只能copy一层,如果列表内的子列表被修改就没办法了。那如果就是不想被一起改了呢?就可以使用深copy,不管多少层都能拷贝。但是需要导入copy模块。
import copy list1 = [[1,2],3] list2 = list1 list3 = list1.copy() list4 = copy.deepcopy(list1) list1[0][0] = 0 print(list2,list3,list4) # 输出结果 [[0, 2], 3] [[0, 2], 3] [[1, 2], 3] 这回终于对了copy模块里的deepcopy方法就是我们说的深copy了,但是基本上是用不上的。
元组与列表相同,用来存储数据,但是元组最大的特点是不可随意添加修改和删除。元组其实就是只读的列表。元组由 ( ) 来表示。
# 创建空元组 tuple1 = () tuple2 = tuple() print(tuple1,tuple2) # 创建含有一个元素的元组 tuple3 = (1,) # 逗号非常重要 tuple4 = (1) # 如果不加逗号的话 print(type(tuple3),type(tuple4)) # 输出结果<class ‘tuple‘> <class ‘int‘> # 创建多个元素 tuple5 = (1,2,3,4) tuple6 = tuple([1,2,3,4])
元组与列表一样,都是根据索引值获取元组内的元素,但是不能进行修改,一旦修改就会报错。不过如果元组内有列表,可以修改列表内的元素。
>>> t = (1,2,[3,4]) >>> t[0] = 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: ‘tuple‘ object does not support item assignment >>> t[-1][0] = 0 >>> t (1, 2, [0, 4])
由于元组不能修改,所以没办法删除元组内的元素,但是可以通过 del 删除整个元组。
>>> t = (1,2) >>> del t >>> t Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name ‘t‘ is not defined
元组的切片与列表相同,也是属于对原元组的拷贝,并不会修改原来的元组。
元组的方法少得可怜,只有count(value)、index(value,start,stop)两种。这两种方法与列表的使用一模一样,这里就不多说了。
字典是一种映射类型,在字典中有两种值:键(key)和值(value)。键就是关键字,而值就是键的映射对象,称为键值对,即键和值是一一对应的关系,一对键值叫做一项。所以,键在字典中必须具有唯一性。正因为字典有键的存在,字典就不需要索引值了,所以字典是无序的。另外,Python的字典在有些地方叫做哈希(hash),而有些地方叫做关系数组,其实都是字典。字典使用很简单{key:value},用大括号括{ }起表示字典,键在前值在后,中间冒号隔开,如果有多对键值,用逗号隔开。
字典没有了索引值,取而代之的是通过键key来提取和修改值value。
上述方法中直接通过键取值,如果键不存在则会报错。为了不报错,可以使用get方法。get(key[,default=None])方法可以根据键获取值。如果键不存在,则返回设置的第二个参数,如果第二个参数没设置(默认状态)则什么也不返回。
>>> d = {‘a‘:1,‘b‘:2,‘c‘:3} >>> d.get(‘a‘) 1 >>> d.get(‘d‘,‘nothing‘) ‘nothing‘
setdefault(key[,default=None])方法可在字典中创建新的键值。当输入的键参数存在于字典中,则返回该键的值,如果不存在,则在列表中创建该键并将设置的第二个参数作为该键的值,如果没有设置第二参数(默认状态)则该键没有值且什么也不返回。
>>> d = {‘a‘:1} >>> d.setdefault(‘a‘,2) 1 >>> d {‘a‘: 1} >>> d.setdefault(‘b‘,2) 2 >>> d {‘a‘: 1, ‘b‘: 2}
fromkeys(iterable, value=None)创建一个新的字典,以第一个参数可迭代对象里的元素作为字典里的键,以第二个参数value作为所有键的值,如果没有输入value则没有值。
>>> dict.fromkeys(‘ab‘) {‘a‘: None, ‘b‘: None} >>> dict.fromkeys(‘ab‘,1) {‘a‘: 1, ‘b‘: 1}
字典的删除有4种方法:del 语句、pop(key[,default=None])、popitem()、clear()。
del 语句可删除项,也可直接删除整个字典,与列表元组类似。
pop(key[,default=None]),通过键将值删除并返回该值。如果键在字典中不存在,则会返回设置的第二个参数,如果第二个参数没设置(默认状态)则会报错。
popitem()方法随机移除一项键值,并将由键和值组成的二元组(两个元素的元组)返回。当字典为空时使用该方法报错。
clear()方法与列表一样,直接删除字典中的所有项,变回空字典。
d = {‘a‘:1,‘b‘:2,‘c‘:3,‘d‘:4} del d[‘c‘] d.pop(‘d‘,‘remove d‘) # d.pop(‘e‘) d.popitem() d.clear()
dict1 = {‘a‘:1,‘b‘:2} # copy() dict2 = dict1.copy() print(dict2) # keys() print(dict1.keys()) # values() print(dict1.values()) # items() print(dict1.items()) # update([iterable]) dict1.update([(‘c‘,3),(‘d‘,4)]) print(dict1)
集合最主要的作用是用来去重和进行关系测试。集合表示方法也使用 { } 大括号表示,但与字典不同的是,集合里的元素不是键值对。集合也是无序,不能用索引值访问其中的元素。
# 创建空集合 s = set() # 创建多元素集合 s1 = {1,2,3,4} s2 = set([1,2,3,4])
>>> a = [1,2,4,4,2,1,3] >>> a = set(a) >>> a {1, 2, 3, 4}
set1 = {1,2,3,4,5,6} set2 = set([5,6,7,8,9,0]) print(set1,set2) #交集 print(set1.intersection(set2)) # 同 set2.intersection(set1) print(set1 & set2) print(set1.isdisjoint(set2)) # 没有交集返回真,有交集返回假 #并集 print(set1.union(set2)) # 同 set2.union(set1) print(set1 | set2) #差集 print(set1.difference(set2)) # in set1,not in set2 print(set2.difference(set1)) # in set2,not in set1 print(set1 - set2) # set2 - set1 #对称差集 print(set1.symmetric_difference(set2)) # 同 set2.symmetric_difference(set1) print(set1 ^ set2) #子集、父集 set3 = {1,2,3} print(set3.issubset(set1)) print(set3 <= set1) print(set1.issuperset(set3)) print(set1 >= set3)
# 添加 s1 = {1,2,3} s1.add(4) s1.update([4,5,6]) print(s1) # 删除 s2 = {1,2,3,4,5} s2.remove(2) # 要删除的元素不在集合内报错 s2.pop() # 随机删除一个元素并返回该元素 s2.discard(5) # 要删除的元素不在集合内则什么也不做 s2.clear() # 清空集合 #不可变集合 s3 = frozenset(s1) s3.add(4) # frozenset后不可变,类似元组,所以会报错
在python中,我们对数据类型还有另外一种分类方式,我们给数据类型分为可变数据类型和不可变数据类型。
可变类型:列表、字典、集合
不可变类型:数字、字符串、元组
那么什么是可变、不可变类型呢?像列表、字典、集合等可以随意修改就是可变,而数字、字符串、元组等不能修改,只能被重新赋值,这就是不可变。
# 内存上来看 >>> l = [1,2,3] >>> id(l) 2720506866312 >>> l[0] = 0 >>> id(l) 2720506866312 # 修改后内存地址不变 >>> a = 1 >>> id(a) 140722283205664 >>> a += 1 >>> id(a) 140722283205696 # 修改后内存地址变化,不是原来的变量了
hash也就是哈希,通过一定的算法将不可变的值转换成一串数字。hash值的计算过程是依据这个值的一些特征计算的。因此,可变的数据类型是不可以被hash的,如果一个值可以hash那么说明这是一个不可变得数据类型。
>>> hash(‘你好‘) -1330917122128407250 >>> hash([1,2,3]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: ‘list‘
原文:https://www.cnblogs.com/yao931104/p/10367662.html