1、 如何来进行对象的拷贝
在进行对象拷贝的时候,一不小心就会变成了对象引用,在赋值的时候使用的是引用,而在其他的例如a=【】的时候是对象的绑定。
>>> list1
['kel', 2]
>>> list2 = list1
>>> list2
['kel', 2]
>>> list2[0]='changed list 2'
>>> print list1,list2
['changed list 2', 2] ['changed list 2', 2]
在将list1赋值给list2的时候,然后修改其中一个值,那么两个都会发生改变,因为在这种情况,两者都是引用,只是绑定了不同的变量,引用指向的是同一个对象,在修改其中一个对象的时候,实际上两者都发生了改变,那么在这种情况下,如果要获得一份拷贝,那么可以用到copy模块。
copy模块中提供了两个方法,一个是copy方法实现的是浅拷贝,一个是deepcopy方法实现的是深拷贝,具体描述如下:
对象的浅拷贝copy.copy:生成了新对象,但是对象内部的属性和内容依然引用的是原对象,从而操作速度快,并且节省内存;
对象的深拷贝copy.deepcopy:在拷贝容器对象的时候,递归的拷贝其内部引用的对象-包括所有的元素,属性,元素的元素和元素的属性
>>> import copy
>>> list1 = [[1,2,'kel'],[1,2]]
>>> list2 = copy.copy(list1) #使用浅拷贝生成了一个新的对象,但是里面的对象依旧是原来对象的引用
>>> print list1,list2
[[1, 2, 'kel'], [1, 2]] [[1, 2, 'kel'], [1, 2]]
>>> list1[0][2] = 'changed'
>>> print list1,list2
[[1, 2, 'changed'], [1, 2]] [[1, 2, 'changed'], [1, 2]] #从而在修改其中一个对象的时候,所有的都会发生改变
>>> list3 =copy.deepcopy(list1) #使用深拷贝进行拷贝所有的元素和属性
>>> print list1,list3
[[1, 2, 'changed'], [1, 2]] [[1, 2, 'changed'], [1, 2]]
>>> list1[0][2]='kel'
>>> print list1,list3
[[1, 2, 'kel'], [1, 2]] [[1, 2, 'changed'], [1, 2]] #在使用深拷贝的时候,改变其中一个对象的子元素,其他的对象不会发生改变
在进行普通的拷贝的时候,如果具有内建方法,那么可以直接使用内建的属性来进行拷贝。
列表:l=list(L),字典:dict = dict(t),集合:s = set(s) 在使用这种方法进行拷贝的时候,方便快捷并且比较简洁。
在提供拷贝的功能的时候,可以使用两种方式,一种是提供__copy__方法,一种是提供__getstate__方法和__setstate__方法,从而可以直接在类中使用拷贝功能。
2、is操作符
is操作符用来检查两个对象是否相同,而不是相等,也就是is主要比较的是引用的地址,而不是内容是否相同:
>>> list1,list2,list3
([[1, 2, 'kel'], [1, 2]], [[1, 2, 'kel'], [1, 2]], [[1, 2, 'changed'], [1, 2]])
>>> list1 is list2
False
>>> list1 is list3
False
从上面可以看到,list1和list2的内容是相同的,但是为False,而list2是由浅拷贝从而生成的新对象,从而引用是不同的,从而返回为False,而深拷贝也是生成了一个新的对象。
3、 拷贝列表
也可以使用其他的方法来进行拷贝,例如在序列中可以使用切片和列表解析
L = L[:] #使用切片
[x for x in L] #使用列表解析
L[:] = [lambda x : x >5 ,for x in L]
在对原来的列表进行操作的时候,不需要重新进行绑定,只要在原来的列表中进行修改即可,从而使用的是原列表的切片方法。
当要对每个元素调用一个函数的时候,最好是使用imap方法,从而和列表解析是差不多的,但是比列表解析更加清晰。
生成器表达式和列表解析的语法相同,不同的在于个一个是圆括号,一个是中括号。,在生成器中,每次仅获取到一个元素。
[x if x>0 else 0 for x in list if x >5]
在列表解析中,条件判断放在前面,而循环放在后面,也可以在后面进行条件判断,但是放前面可以获得不同的值。
4、查找列表中元素,如果存在返回
def get_list(li,i,v=None):
if -len(li) <= i <len(li):
return li[i]
else:
return v
list1 = [1,2,3,'kel']
print get_list(list1,3)
print get_list(list1,8)
定义了一个方法,如果列表的有效索引在列表接收的长度之内,那么就会返回列表的值,如果不存在,那么返回为None
结果如下:
[root@python 410]# python getitem.py
kel
None
从上面可以看到,3在列表索引有效范围为-len(L)到len(L)之间,从而返回了list的值,而当不在这个范围内的时候,返回为默认值None
5、循环访问序列中的元素和索引
在很多时候,需要循环的索引,而在很多迭代中,并不是按照索引值来进行循环的,从而可以使用内建函数enumerate。
循环都是用for进行循环,从而没有索引,如下:
for item in sequence:
process(item)
使用enumerate内建函数后,可以得到索引值:
>>> for index,item in enumerate([1,2,3,4]):
... print index,item
...
0 1
1 2
2 3
3 4
在for的主题中,索引和值可以同时访问。