今天首先要说的是深拷贝和浅拷贝。
copy/deepcopy
我觉得这个问题直接用代码说话比较直观
import copy
a=[1,2,3,4,[1,2,3]]
b=a
c=copy.copy(a)
d=copy.deepcopy(a)
a.append(5)
a[4].append(4)
结果:
a -->[1,2,3,4,[1,2,3,4],5]
b -->[1,2,3,4,[1,2,3,4],5]
c -->[1,2,3,4,[1,2,3,4]]
d -->[1,2,3,4,[1,2,3]]
解释:b是赋值,c是浅拷贝,d是深拷贝,所以得出结论,赋值是对象的引用,引用就是引用的[1,2,3,4,[1,2,3]],当这个值变了,a和b这两个变量还是指向那个地址,所以值变成什么,a和b就指向什么。c是浅拷贝,这个拷贝只有改变内层元素内的值时,才会跟着改变,改变外层的值,不会跟着改变(这里是最难理解和记忆的),d就牛逼了,d是深拷贝,相当于重新创造了一个值和变量,所以不管原有值变得天昏地暗,对d都没有影响。
以上是对于可变对象,那么不可变对象呢?
a=1
b=a
c=copy.cpoy(a)
d=copy.deepcopy(a)
a=2
结果:
a -->2
b -->1
c -->1
d -->1
由此看出,对于不可变对象,浅拷贝之后,其实是原有的a的指向变了,a指向一个新创造的2,而b和c都还是指向原有的1,d是深拷贝,所以肯定是不会有任何变化的,他有一个独立的1指向。
第二个要讲的内容是迭代器和生成器
迭代器和生成器有很多不同的理解,但是我有一个很好的可以区分他们的地方,先不管内部实现的情况下:
迭代器:一个函数内含有iter语句,并且用next方法取值的就是迭代器,如果没有值了,则会抛出异常,这个也是for循环遍历可迭代对象的内部实现原理。
生成器:函数内部有若干个yiled语句,调用一次函数,则生成一个值,然后继续阻塞在下一个yield地方,等待下一次被调用,继续生成制定值,如此循环直到最后一个yield结束。我们知道的xrange()就是一个生成器。
g = ( x*x for x in range(5))
这里的g就是一个生成器,可以用type(g)查看
可以用next方法返回值:g.next()
当没有值再生成是,就抛出一个异常,结束程序
def odd():
print 'step 1'
yield 1
print 'step 2'
yield 2
print 'stet 3'
yield 3
这个odd也是一个生成器
如果函数内可以生成的元素太多,比如有100万个,那么用next方法一个一个去取,那你的取到天荒地老,我们可以用for循环遍历。