数据类型
数据类型
homepage
#数据类型 Python的程序在运行的过程中,变量的值是存储在内存中的。对于不同类型的变量,要使用不同类型的数据类型来进行存储,在这一节里, 我们就来学习变量和数据类型的相关知识。 ##变量 在Python中,实际上变量是内存中的数据与其地址的一个关联。当我们对一个变量进行赋值时,就会将其值存储在内存中。 而调用这个变量的时候,实际上是指向相应内存地址中的值。例如,我们可以用以下代码,对变量a进行赋值: ``` a = 100 ``` 这步操作,就在内存的某个位置存储了整数“100”,并且变量a将指向那个值所在的地址。当我们对变量再次赋值的时候,实际上是一次新的初始化, 变量会指向另外一个位置,而不是修改在相应位置存储的数值。例如下面这个例子: ``` a = 100 b = a a = a + 1 ``` 如果我们这时候分别调用a和b,我们就会发现,a是101,而b仍然是100。在我们进行b = a的操作的时候,b也指向了100所在的那个地址, 而我们对a赋值为101的时候,不是修改了地址中的100,而是使其指向了另外一个在内存中新存储的值101所在的位置。 而出于节省内存的考虑,我们总可以用del()方法来删除一个变量以释放内存。 ##number 我们要介绍的第一种数据类型就是数字。在Python中,数字分为3种,一种是int,也就是整数。一种是float,浮点数,也就是包含小数点的数。 第三种我们在日常的开发中使用较少,是复数。 ###int Int就是单词integer的缩写,在Python中,int这一类型有正负之分,和我们平常书写习惯一致,默认为正数,但是赋值时在前面加负号,就是负数。 int默认为十进制数,但是也可以使用其他进制的数字。首先,典型的在计算机中常用的二进制和十六进制,可以用直接在前面添加“0b”和“0x”的形式。 例如,在下面的代码中 ``` a = 256 a = 0b10000000 a = 0x100 ``` 三次赋值,实际上都是同一个数。 此外,也可以赋值规定进制的数,例如下面的代码中,为变量赋值使用七进制数: ``` a = int('11463', 7) ``` 需要注意的是,熟悉其他编程语言的同学可能知道,在其他的编程语言中,整数可能还有long(长整型)或short(短整型)的类型。在某些历史版本的Python中, 确实存在过long作为数据类型,但是依照目前最新版本的Python的设计,所有的整数均为int,不再有long或者short。 ###float float也就是浮点数,或者说是有小数点的数。float也有正负之分,并且在涉及除法等无法在整数范围内完全进行的操作时,Python会自动将变量转化为float。 如在下面的代码中: ``` a = 10 print(type(a)) a = a / 3 print(type(a)) ``` 我们得到的两次输出就不同了,首先是int型,然后是float型。 尽管变量可能是int型,也有可能是float型,但是在做变量比较,尤其是判断相等时,并不会因为变量数据类型的不同而给出不同的答案。例如下方代码: ``` a = 10 b = 10.0 print(a==b) ``` 运行这段代码的话,我们会得到True的答案。 类似的,在其他语言中,可能会存在double这一数据类型,即双精度浮点数,其中float一般指32bit的浮点数(也就是所谓的float32)而double则为64bit的浮点数(所谓的float64)。 而在最新版本的Python中,我们一般默认float为64bit,因此,Python中不存在double这一类型。 ##boolean boolean也就是布尔数,它只有两个值,True和False。它用来表示真或者假。我们在进行判断时,其结果经常会以boolean的形式来表示 (如果没有出现判断的错误的话)。这常被用在if语句的判断条件或while循环语句的循环条件中,例如在如下代码中: ``` a = 1 while a < 100: print(a) a += a ``` “a < 100”是这个循环不断进行的条件,当这个判断的结果为True的时候,循环继续,反之,结果为False的时候,循环终止。 我们现在看不懂这段代码也没关系,之后我们还会学习相应的逻辑判断语句和循环。 ##string string也就是字符串,用来保存一串文字。我们在“Hello, World”程序中,使程序打印的就是一串字符串。string在Python中的表示形式, 是用**英文的单引号**引起来的一串文字,例如下面的代码中: ``` a = '我不要你觉得,我要我觉得。' print(a) ``` 尽管字符串不能进行减、乘、除等运算,但是字符串与字符串间是可以进行“加法运算”的。其规则为,直接在一个字符串后追加相加的内容。 例如在下面的代码中: ``` a = '这件事不需要讨论,' b = '都听我的。' print(a+b) ``` 得到的输出就会是“这件事不需要讨论,都听我的。” 而另一方面。我们应该注意的是,字符串中的数字等,都已经是作为“文本”的形式了,他们就已经不能和int或者float进行比较或者进行数学运算了。 例如下面的代码,运行的话就会报错: ``` a = 1 b = '1' c = a + b d = (a < b) ``` 而字符串是不是绝对不能“比较大小”呢?其实也不是,例如下面的代码,就是可以运行的: ``` print('B' > 'A') print('我' > '你') ``` 这段代码运行的话,得到的输出就是两个“True”。这是为什么呢?我们如果运行下面的代码: ``` print(ord('A')) print(ord('B')) print(ord('我')) print(ord('你')) ``` 得到的输出分别是“65”“66”“25105”“20320”。这是因为Python中,字符有其相应的编码,而在进行字符比较时,实际上比较的是它们的编码。 并且也可以对编码进行运算,在某些实际应用场景中非常实用(例如大小写字母的转换)。 ###格式化 我们在编写程序时,可能会经常需要输出某句格式化的语句,例如某些查询系统中,我们可能需要输出类似“尊敬的顾客XXX,您目前选用的套餐是XXX套餐, 本月产生的费用为XX元。”其中顾客的姓名、套餐类型,费用都可能是要从庞大的数据库中查找出的,这种情况下,我们可以参考下面这段代码: ``` a = '黄店长' b = '特惠单人套餐' c = 150 print('尊敬的顾客%s, 您目前选用的套餐是%s, 本月产生的费用是%d元'%(a,b,c)) ``` 运行这段代码的话,我们得到的输出结果是“尊敬的顾客黄店长, 您目前选用的套餐是特惠单人套餐, 本月产生的费用是150元”。通过这种方式, 我们就可以格式化字符串了。我们在字符串中放入**占位符**, 然后在百分号后面,按照顺序给出相应的变量。 |占位符|数据类型| |:---:|:---:| |%s|string| |%d|int| |%f|float| 实际上,对于现行版本的Python,如果你记不清楚应该用哪个占位符,一律使用%s也可以,将一切内容**转化**为字符串来输出。 上面的代码例子中,全部使用%s,也可以得到相同的结果。 不过,特别的,对于%d和%f,我们有的时候可以有更加多样的式样可以选择,例如,运行以下代码体会其中的不同: ``` a = 123.456 print('我要打印的内容是%04d'%a) print('我要打印的内容是%.2f'%a) ``` 格式化还有别的形式也可以进行,例如使用format method,不过上面介绍到的这种方法最为便捷并且总是可以使用,如果我们今后遇到了其他的形式, 我们到时候再做介绍。 ##tuple、list和set tuple、list和set都是Python中常用的集合的数据类型,可以包括多个元素在其中(当然也可以只有一个元素或者直接是空的),而其又各有不同。我们来看以下表格: |数据类型|表示符号|特点| |:---:|:---:|:---:| |tuple|() 即一对小括号|元素可重复,不可更改| |list|[] 即一对中括号|元素可重复,可更改| |set|{} 即一对大括号|元素不可重复,可更改,自动排序| 通过以上表格,我们可以看出tuple、list和set中的相同点和不同点。我们接下来介绍对它们的赋值。对它们的赋值,有两种形式, 但是其结果都是相同的,我们来分别对其进行赋值(1,3,5,7): ``` t = (1, 3, 5, 7) l = [1, 3, 5, 7] s = {1, 3, 5, 7} ``` 这样做,和下面的代码是完全相同的: ``` t = tuple((1, 3, 5, 7)) l = list((1, 3, 5, 7)) s = set((1, 3, 5, 7)) ``` 使用这种方法时,注意是两层括号。 ###tuple、list和set的操作 在Python中,我们可以对tuple、list和set进行一些操作,例如调用其中的元素,对其中元素进行增减等等。 ####调用与切片 当我们对tuple或者list进行赋值的时候,其中的元素会保持我们赋值时填入元素的顺序,我们就可以调用tuple和list中的指定某一个或者某几个元素。 如果我们只是想调用其中某一个元素的话,就非常简单,例如下面的代码: ``` l = [1, 3, 5, 7] a = l[2] print(a) ``` 这段代码中,我们为a赋值为list l中序号为2的元素,并且将其打印。这里要注意的一点是,**序号是从0开始的,也就是说,其中排第一的元素序号是0**。 这一点很多初心者会忘记,导致之后的编程中,出现错误而还没有发觉。类似的,我们还可以指定其中倒数第N个元素,例如,有一个列表l, 其中最后一个元素,就是l[-1] 而如果我们想要调用其中连续的几个元素,我们可以采用“切片”的操作。参考下面的代码: ``` l = [0, 1, 2, 3, 4, 5, 6, 7, 8] a = l[2:5] print(a) ``` 我们得到的结果是[2, 3, 4]。这时候要注意切片的上界和下界,其中包括了切片的下界,不包括其上界,这个地方可能需要注意一下。 另外,进行切片时,也不一定要挨个遍历其中元素,可以指定步长,例如运行以下代码: ``` l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] a = l[2:7:2] print(a) ``` 得到的结果是[2, 4, 6]。步长也可以指定为负数,例如运行下面的代码: ``` l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] a = l[-3:-9:-2] print(a) ``` 体会负数的步长在这里的意义。 特别的,当我们在切片时,如果下界为从头开始或者上界为到最后为止,那么相应的序号可以省略,例如: ``` l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] a = l[:5] b = l[5:] print(a,b) ``` 输出的结果为[0, 1, 2, 3, 4]和 [5, 6, 7, 8, 9, 10]。 指定序号调用和切片操作不只可以对list进行,也可以对tuple进行,但不能对set进行切片。由于set会对元素进行重排序,所以set中的元素顺序不是一开始放入的顺序, 无法对set中的元素进行指定序号的调用。不过这两种操作同时也可以对字符串进行,请在字符串上进行实验,体会其效果。 ####编辑 对这些数据类型,我们也可以进行一些编辑操作,下面我们来具体一一学习。 #####指定序号的元素赋值 我们可以对一个list中指定序号的元素进行赋值,像下面的代码中一样: ``` l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] l[5] = 17 print(l) ``` 运行这段代码,我们就可以发现,l变成了[0, 1, 2, 3, 4, 17, 6, 7, 8, 9, 10]。需要注意的是,这种赋值法不适用于tuple和set。 因为这是指定序号的编辑,set不可指定序号而tuple不可编辑,但这种方式同样适用于string。 #####对集合内元素的添加和移除 我们经常会遇到需要对集合内元素进行添加或移除的情况,对于list,我们应当熟悉以下几种操作。 |Method|描述| |:---:|:---| |remove()|移除list中的某个指定元素| |pop()|从list中取出一个元素(从最后一个开始)| |append()|在列表末尾追加一个元素| |insert()|在列表指定位置添加一个元素| 我们来用以下代码来体会pop()方法的运用,其他的方法请同学们自行编写代码运行体会。 ``` l = [1, 2, 3, 4, 5, 6, 7, 8] a = l.pop() print(a, l) ``` 对于set,以上的方法所对应的情况: |Method|描述| |:---:|:---| |remove()|移除set中的某个指定元素| |pop()|从set中取出一个元素 **(从第一个开始)**| |append()|由于set的重排序机制,无法指定末尾,可以使用add()方法| |insert()|无法在set中指定某一序号,不适用于set| #####集合元素的多样性 在这节中,我们对几个集合进行讲解的时候,基本上各集合中元素我们都是以int为例的。然而实际上各个集合中,可以接受多种元素, 例如,我们甚至可以对一个tuple这样赋值: ``` t = (1, 1.0, '1', [1], True) ``` 我们可以发现,无论是整型还是布尔数,都可以被tuple接受,甚至列表也可以。不过set是不接受列表的,这点请注意。运行下面这段代码, 你可能会发现有趣的事情,并想一想为什么。 ``` s = {1, 1.0, '1', True} print(s) ``` #####编辑与重赋值 这里要强调一下对变量的编辑和重赋值的区别。我们之前强调过,对一个变量进行重赋值时,将会在内存中开辟新的存储空间,将新的值存储进去, 并使变量重新指向新的内存位置。但是,当我们对一个变量进行编辑的时候,则是对内存中相应位置中的值直接进行编辑,变量依然指向原位置。 这一点与重赋值是不同的,我们可以从下面的一段代码中体会。 ``` l = [1, 2, 3, 4, 5, 6] n = [1, 2, 3, 4, 5, 6] ll = l nn = n l[2] = 100 n = [1, 2, 100, 4, 5, 6] print('ll的值是%s' % ll) print('nn的值是%s' % nn) ``` 如果我们运行上面这段代码,我们可以明显发现,我们对l进行的是编辑操作,ll本来和l一样指向同一个内存位置,我们对内存中这个位置进行编辑之后, ll的内容也随着发生了改变。而我们对n进行的是重赋值操作,这之后n的新值被存储在了新的内存位置,n指向了这个新的位置,而nn还指向原来的内存位置。 因此,nn的内容没有随着n的重赋值而发生改变。 #####tuple的不可编辑性 我们之前提到了,tuple是不可编辑的,但是,对于tuple内的元素,又是怎么样的呢?我们来运行下面的这段代码, 看一下能否对tuple中的元素进行编辑和重赋值。 ``` l1 = [1, 3, 5, 7] l2 = [2, 4, 6, 8] t = (l1, l2) print(t) l1 = [2, 3, 3, 3] l2[3] = 100 print(t) ``` 我们可以看到,被重赋值的l1并没有改变tuple中的内容,但是被编辑的l2使tuple中的内容发生了改变。也就是说,尽管tuple是不可编辑的, 我们不能向tuple里面添加或者删减元素,但是,对元素的编辑,会影响到tuple的内容。至于重赋值为什么没有引起内容的改变, 参考上面我们讲到的编辑与重赋值的区别,想一想为什么。 ##dict dict是一种相对比较特殊的集合的数据类型,dict中的元素为对应的一对值,为key:value的模式。其中key的内容不可重复, 但value的内容不受限制。这一特性使得它可以很方便地被用在一些实际应用场景中,例如,我们需要调用一个班的学生的各种数据。 我们希望至少要为每个学生记录他们的姓名、年龄、身高、分数、学号信息。以下面两位学生为例: |Name|Age|Height|ID|Score| |---|---|---|---|---| |Sam|15|178|209001|87| |Tom|14|169|209002|98| 这个时候,我们就可以用下面这段代码,为Sam记录这些信息: ``` sam = dict(Name='Sam', Age=15, Height=178, ID='209001', Score=87) print(sam) ``` 或者使用这种形式,为Tom进行记录: ``` tom = {'Name':'Tom', 'Age':14, 'Height':169, 'ID':'209001', 'Score':98} print(tom) ``` 而我们需要调用其中的某一项的时候,则可以像下面这样: ``` print(tom['Name']) ``` ###dict的编辑 dict中的元素是可以编辑的,也可以增减其中的元素。例如,我们想给Tom增加一项体重的信息,可以直接使用下面的代码: ``` tom['Weight']=63 ``` 至于删除,则可以用以下的代码: ``` del tom['Weight'] ``` 我们也可以清除掉一个dict中的所有元素,使用类似下面的代码: ``` tom.clear() ```
content
戻る