变量和数据类型要点小结
1.变量和常量
1.1.变量:
python中的变量定义不像C语言、Java等需要在第一次使用前或使用时明确变量类型。可以直接使用赋值语句对一个变量进行相应的赋值,
例如:str_ = 'string' ==> 此时如果使用type(str_)就会发现,str_的类型已经是字符串了(可以使用字符串有关的内置方法)
此时,如果继续使用 str_ = 123 ==> 此时type(str_)则会显示str_已经是一个int类型(变量所赋值决定了其数据类型),而在
C语言、Java中是不允许直接将整型数据直接赋给字符串类型的。
1.1.1.变量名命名规范:
1.变量名由大小写英文字母、数字和下划线_组成
2.变量不能用数字开头
3.变量尽量不要和Python关键字重合(比如:and、or、not等,否则可能导致Python原有关键字发挥不出作用)
1.2.常量:
相对于变量,常量并不是说永远不变,而是指在某一过程中,它的值固定不变。
例如,在程序编写过程中,我们可以把频繁使用的一些内容(某个字符串、某个数字,例如Web项目中约定的一些状态码等)抽离出来。
像变量一样为其定义一个有意义的名称去关联它,在要用到这个值时,用这个名称去引用这个值即可。
这样做的好处是在这个值需要修改时,只需要修改其对应常量名称对应的常量值一处即可,不像之前的要在所有引用的地方重复定义。
这里其实隐含了封装的思想。
1.3.常量池:
关于"池",类似的还有线程池、IP代理池等。通俗一点理解,像我们日常生活中的蓄水池,就是预先将一类对象准备好放在一个地方(池),
用的时候直接取出来用即可,用完再放回去。而不是每次用的时候才临时创建,随着程序运行和结束或手动或被动的销毁。比如线程池,
如果要用到的线程量很大,那么不妨一次性创建一批线程组成线程池,随取随用,而不用每次都创建一个线程(创建太过频繁时花费的代价
太大)。
常量池也是类似的,在很多项目中,都会涉及到常量池,将一些约定好的或是频繁会用到的值放在一个固定的地方(可以是单独的文件)。
随着项目的开发,可以不断进行常量池的扩充。这样在涉及到修改时(特别是项目后期修改很麻烦)可以很方便。
池的思想也是一个很好的思想。。
2.数据类型
2.1.Python中的数据类型:
整数int 字符串str 浮点数float 布尔型bool 列表list 字典dict 集合set 元组tuple;
2.1.1.现对这些数据类型进行简单介绍:
1.整数即整型常量-1, 0, 1, 2, 3...
2.字符串即由各种字符构成的字符序列,一般形式为"sdf14545+*555dasd",python中也可用单引号包含字符序列,多行用三引号,
或+连接,格式化的方法也有多种,常见的有f'{变量名}xxx'、'%s-%d'.format(a,b)等;
3.浮点数也与其他语言一样,可以理解为类似于123.456的小数;
另外对于科学计数法:在Python中,把10用e替代,比如:1.23x10^9就是1.23e9
4.布尔型即True或False,表示真或假,特别在python中真和假的首字母是大写;
5.列表即类似于数组形式[1, 2, 3],但是其中的元素可以理解为一个对象,因此除了基本类型,还可以放其他对象类型的元素;
6.字典即键值对序列,且键不能重复,其值也是可以理解为一个对象,因此可以是基本类型、列表、字典及其他自定义对象;
7.集合可以理解为数学意义上的集合,因此集合具有无序性,互异性、确定性;因此常常可以用来作列表的去重操作;
8.元组即形如(1, 2)、(a, b, c)等(此处的abc为任意对象),根据元素的个数可以称为二元组、三元组等;
2.2.可变类型和不可变类型:
首先给出结论再作说明:Python中的可变类型有:列表、字典、集合;不可变类型有:整数、字符串、浮点数、布尔型、元组。
所谓可变和不可变,以 key=value做解释。可变和不可变指的均是key被定义为value后,能否对value进行修改,而不是
能否对key进行修改,对key的修改其实是对变量key的重新定义,新的value会取代旧的value。这样说可能理解起来有点抽象。
我们将value看做一个对象(其实任何一个列表、元组、字典等数据均是一个对象),我们所说的可变就是对这个对象进行修改,而
不是对其绑定的变量重新赋值来覆盖旧的对象。这里给出一个实例:
例如 list_=[1, 2, 3] ==> list_[1]=4 ==> [1, 4, 3] 这是修改了value数据对象的值;
而如果list_=[1, 2, 3] ==> list_=[1, 4, 3] ==> [1, 4, 3] 这就是对key进行了重新定义,覆盖了旧的value;
2.2.1.可变类型:
结合上述分析,可变类型我们可以拿列表简单来解释,列表为什么可变?因为列表这个对象内部还包含了很多的元素,这些元素可以看
做是一个个子对象,将这些子对象用列表这种数据结构组织起来后,整体共同形成了这个列表对象。因此列表在定义以后,可以通过
下标或者append、pop等方法对这个列表内的元素进行修改,这就是对列表对象进行了修改,而对于其中的元素(子对象),其实
是被重新定义或修改了的。这里为什么说是"或修改"?,因为重新定义是针对列表内的元素为不可变类型,而如果列表嵌套了列表
或字典、甚至是我们自定义的对象,
例如:list_=[[1, 2], [3, 4], [5, 6]] ==> list_[0][1]=0 ==> [[1, 0], [3, 4], [5, 6]] 这就是通过修改其
子元素修改了list_绑定的这个列表对象。
对于其它可变类型,我们也可做类似的理解,此处不一一举例了。
2.2.2.不可变类型:
理解了可变类型,不可变类型就比较好理解了,例如一个数字123,它本身就是一个个体,我们虽然可以得到它各个位上的数字,但是
并不能说124还是原来123那个数字对象;
同理对于字符串str_='string',Python中我们虽然可以通过str_[3]查询到它的第四个字母是i,但是他是一个不可分的个体,任何
的像'strong'都是一个新的字符串对象,而不是在string的基础上进行了部分修改。可能理解起来还是有点抽象。
那么我们可以再拿布尔类型来举例:
对于value=True,我们只能通过value=False对变量value的值进行重新定义,而不能够直接对True进行任何修改操作。因为True
永远都是True,False永远都是False,他们是唯一的不可变的,他们代表的含义也是不可变的。这就是不可变类型。
至于元组,虽然也能存放其它可变对象,但是按照规定,元组类型的值确实是不可以改变的,只能进行访问。
如果对于不可变类型强行修改其内容就会引发报错,例如str_='string' ==> str_[3]='o'就会报错,因为这样是不被允许的。
2.2.3从内存角度理解可变类型与不可变类型
如果上述内容理解还是不太容易,我们可以从内存角度理解。实际这些数据创建时会被放在某个存储单元内,而通过变量名指向了这个
存储单元,然后就通过变量名对其进行引用。Python的内置方法id(Obj)可以查看Obj这个对象在内存中的地址id。
1.对于可变类型列表:
listA = [1, 2, 3] ==> print(id(listA)) ==> 2550791267392
listA[0] = 0 ==> print(id(listA)) ==> 2550791267392 (此时listA=[0, 2, 3])
listA = [1, 2, 3] ==> print(id(listA)) ==> 2550526722176
1,2行可以看出修改列表对象listA的某个元素,它的内存ID没变,说明还是原来那个对象;而1,3行对listA进行重新定义,
可以看出listA绑定到了一个新的内存ID,说明并不是在其原本的对象基础上进行了修改,而是重新绑定到了一个新的对象。
2.对于不可变类型:
tupleA = (1, 2, 3, 4) ==> tupleA[0] = 0
==> TypeError: 'tuple' object does not support item assignment 不支持修改元素
tupleA = (1, 2, 3, 4) ==> print(id(tupleA)) ==> 2078685627152
tupleA = (0, 1, 2, 3) ==> print(id(tupleA)) ==> 2078760469984
第1行可以看出元组不支持修改元素,即不可变类型。从2、3行对比可以看出重新赋值tupleA绑定到了一个新的内存ID,说明
其重新绑定到了一个新的对象。