1、可变对象和不可变对象
在python中,主要的数据类型为字符串,数字,列表,元祖和字典,其中字符串,数字和元祖为不可变类型,而列表和字典属于可变类型。
在强调可变类型和不可变类型的时候,只要是在复制的时候,是浅拷贝还是深拷贝,一个数据的修改会不会造成另外的一个引用也发生变化,如下所示:
>>> alist = [1,2] (可变对象list)
>>> blist = alist (alist和blist指向同一个对象,也就是引用了同一块内存地址,内存地址中放着列表)
>>> blist[1]="changed" (修改其中的值)
>>> alist
[1, 'changed']
>>> blist (由于引用的是同一个对象,从而两者都会发生变化)
[1, 'changed']
>>> alist is blist (is表示两者是否同一个对象,也就是引用的内存地址是否相同)
True
>>> atuple = (1,2,[1,2]) (不可变对象tuple)
>>> btuple = atuple (两者引用同一个对象)
>>> id(atuple) (指向的内存地址相同)
139987083454816
>>> id(btuple)
139987083454816
>>> atuple[2][1]="changed" (元祖的值不可变,但是如果包含了可变对象,还是可以变化的)
>>> atuple,btuple(两者都发生了变化)
((1, 2, [1, 'changed']), (1, 2, [1, 'changed']))
>>> id(atuple),id(btuple)(引用的内存地址未发生变化)
(139987083454816, 139987083454816)
从而在进行复制的时候,需要小心,有的时候在进行赋值的时候,可能在其他的地方发生了修改,在直接赋值的时候,基本上是浅拷贝,如果要想重新创建一个对象,从而可以使用深拷贝,如下所示:
>>> import copy(导入模块copy,主要用来做深拷贝)
>>> alist = [1,2,3]
>>> blist = copy.deepcopy(alist) (深拷贝的引用赋值给blist)
>>> id(alist),id(blist) (两者指向的对象不同)
(139987097637376, 139987097642696)
>>> alist[1] = "changed"
>>> alist,blist (一个修改不会影响另外的一个对象)
([1, 'changed', 3], [1, 2, 3])
2、字符串和数值类型
字符串类型和数值类型都是不可变对象,但是字符串是一个容器对象,从而可以进行切片,可以看做是一个序列,可以使用下标来进行引用,如下所示:
>>> a = "hello world"
>>> b = a (两者引用同一个对象)
>>> id(a),id(b)
(139987083474768, 139987083474768)
>>> a = "changed" (修改的时候,不会同时发生修改,会创建一个新的对象,从而体现了字符串的不可变对象)
>>> a,b,id(a),id(b) (id表示内存地址,也就是变量指向的地址)
('changed', 'hello world', 139987083475632, 139987083474768)
>>> a[1:2] (字符串属于容器类型,从而可以做切片操作,表示取第一个元素)
'h'
>>> a[1:3:1] (扩展的切片操作,可以指定开始位置,结束位置和步长)
'ha'
>>> a[::-1] (将字符串进行倒序输出,-1表示最后一个元素)
'degnahc'
>>> a[-1:-3:-1] (从左到右是0到len(a),从右到左是-1到-len(a))
'de
>>> a.startswith('hello') (字符串方法,判断以什么开头)
False
>>> " " .join(a) (连接容器类的元素)
'c h a n g e d'
>>> a = 1.0 (数值类型)
>>> b = 1.0
>>> id(a),id(b) (不可变对象两者引用的内存地址不同)
(38405792, 38405768)
>>> a = 1
>>> b = 1
>>> id(a),id(b) (python在内部会高效缓存简单数字0-100,从而两者的内存地址一致)
(38334808, 38334808)
3、列表和元祖
列表属于可变对象,元祖属于不可变对象,列表中的值能直接进行修改,而元祖的值是不能修改的,但是如果元祖中包含了可变对象,那么依旧是可以修改的,两者都是序列类型,从而可以通过下标进行引用,在列表包含的方法比较多,而元祖由于不能发生改变,从而没有啥方法,基本的操作如下所示:
>>> alist = [1,2,3,"xyz"] (创建list)
>>> alist[1](使用下标取值)
2
>>> alist[2:](list属于序列,从而支持切片操作)
[3, 'xyz']
>>> alist.append("add item")(在list后面添加新元素)
>>> alist.count("add item")(统计list中元素的个数)
1
>>> alist.index(1)(取出第一次出现值1的索引)
0
>>> alist.insert(1,"add position1")(在某个位置插入新的元素)
>>> alist.sort()(list是有序的,从而可以对list进行排序)
>>> alist
[1, 2, 3, 'add item', 'add position 1', 'xyz']
>>> alist.remove("xyz")(移除元素)
>>> alist
[1, 2, 3, 'add item', 'add position 1']
>>> alist.pop()(随机pop一个元素,返回值)
'add position 1'
>>> alist.pop(1)(指定位置pop元素,返回值)
2
>>> alist
[1, 3, 'add item']
>>> alist.reverse()(将list进行反转操作)
>>> alist
['add item', 3, 1]
>>> blist = [1,2,3]
>>> alist.extend(blist)(扩展列表,将另外一个列表加入到现在的列表中)
>>> alist
['add item', 3, 1, 1, 2, 3]
>>> len(alist)(列表的长度)
6
>>> atuple = (1)
>>> type(atuple)
<type 'int'>
>>> atuple = (1,) (在只有一个元素的时候创建tuple,必须使用逗号)
>>> type(atuple)
<type 'tuple'>
>>> atuple[1] (超出索引范围会报错)
Traceback (most recent call last):
File"<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> atuple[0](根据索引取值)
1
>>> atuple.count(1)(统计元素的个数)
1
>>> atuple.index(1)(找出元素的索引)
0
4、字典
字典是可变对象,并且是属于序列对象,以键值对的形式存在,在访问的时候,不同于list和typle,必须通过映射的方式来进行访问,也就是必须通过键,然后才得到相应元素的值,如下所示:
>>> adict = {}(创建空字典)
>>> adict ={"key":"value","age":22} (创建字典有很多方式,这是其中之一)
>>> adict['key'](字典必须通过键来进行引用字典的值)
'value'
>>> adict.items()(查看键值对的元祖的列表)
[('age', 22), ('key', 'value')]
>>> adict.keys()(查看字典的所有键,返回一个列表)
['age', 'key']
>>> adict.values() (查看字典的值,返回一个列表)
[22, 'value']
>>> adict.iterkeys()(查看字典的键,返回的是一个迭代器)
<dictionary-keyiterator object at0x7f5148613260>
>>> adict.itervalues()
<dictionary-valueiterator object at0x7f51486135d0>
>>> for i in adict.iterkeys():(循环迭代取值)
... print i
...
age
key
>>> adict.viewkeys()
dict_keys(['age', 'key'])
>>> adict.viewvalues()
dict_values([22, 'value'])
>>> adict.viewitems()
dict_items([('age', 22), ('key', 'value')])
>>> for i in adict.viewkeys():
... print i
...
age
name
key
>>> adict
{'age': 22, 'key': 'value'}
>>> bdict ={"name":"kel"}
>>> adict.update(bdict)(将一个字典加入到另外一个字典之中)
>>> adict
{'age': 22, 'name': 'kel', 'key': 'value'}
5、几个有用的内置函数
几个比较有用的函数如下所示:
>>> dir()(查看当前环境)
['__builtins__', '__doc__', '__name__','__package__', 'atexit']
>>> type(int)(type用来查看对象的类型)
<type 'type'>
>>> a = 1
>>> id(a)(id用来查看对象的内存地址)
33026392
>>> b = 1
>>> a is b (is用来比较两个对象的引用是否相同,也就是内存地址是否相同)
True
>>> dir(a) (dir可以查看对象的函数和属性)
['__abs__', '__add__', '__and__','__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__','__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__','__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__','__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__','__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__','__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__','__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__','__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__','__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__','__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length','conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> help(a)