zoukankan      html  css  js  c++  java
  • python中的对象拷贝

           python中。进行函数參数传递或者返回值时,假设是一般的变量,会拷贝传递。假设是列表或字典则是引用传递。那python怎样对列表和字典进行拷贝传递呢:标准库的copy模块提供了两个方法:copy和deepcopy方法。

    1. copy.copy 浅拷贝 仅仅拷贝父对象,不会拷贝对象的内部的子对象。


    2. copy.deepcopy 深拷贝 拷贝对象及其子对象

    见下例:

    import copy
    a = [1, 2, 3, 4, ['a', 'b']]  #原始对象
    
    e = a[:] 		#利用分片操作进行拷贝(浅拷贝)
    b = a  		#赋值。传对象的引用
    c = copy.copy(a)  	#对象拷贝,浅拷贝
    d = copy.deepcopy(a)  	#对象拷贝,深拷贝
    
    a.append(5)  		#改动对象a
    a[4].append('c') 	#改动对象a中的['a', 'b']列表子对象
    
    print 'a = ', a
    print 'b = ', b
    print 'c = ', c
    print 'd = ', d
    执行结果:

    a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
    b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
    c =  [1, 2, 3, 4, ['a', 'b', 'c']]
    d =  [1, 2, 3, 4, ['a', 'b']]
    e =  [1, 2, 3, 4, ['a', 'b', 'c']]

    分析:

          b是a的一个引用。两者指向的对象同样,打印结果必定同样。c仅仅拷贝了a的中的父对象。对于a中嵌套的子对象列表并没有拷贝,所以c中的1,2,3,4是拷贝得到的副本,属于自己的,但嵌套的子对象列表还是a原来的。d的话,因为是深拷贝,所以子对象父对象都是拷贝生产的新的副本。全然不所原来a的影响。至于e,分片操作的效果等价于浅拷贝,结果和c同样。


    以下以列表为例,看看函数參数传递和返回值中,是怎样进行引用传递的:

    #coding=utf-8
    def ggg():
    	l = [1, 2, 3]           #局部变量
    	print 'local var ', l
    
    	return l
    
    def fff(l):
    	l.append(100)
    	l[2].append('c')
    
    	print "global var ", l  #全局变量
    
    	return l
    
    a = ggg()
    print a 
    a.append(10)
    print a
    ggg()
    
    print '
    
    '
    
    a = [1, 2, ['a', 'b'], 3]
    b = fff(a)
    print a
    b.append(1000)
    print b
    print a
    

    执行结果:

    local var  [1, 2, 3]
    [1, 2, 3]
    [1, 2, 3, 10]
    local var  [1, 2, 3]


    global var  [1, 2, ['a', 'b', 'c'], 3, 100]
    [1, 2, ['a', 'b', 'c'], 3, 100]
    [1, 2, ['a', 'b', 'c'], 3, 100, 1000]
    [1, 2, ['a', 'b', 'c'], 3, 100, 1000]

    分析:

    a接受函数ggg返回的局部变量。但改动a后第二次调用函数ggg,ggg内的局部变量l并没有受到影响,课件ggg返回局部变量时是拷贝传递,就像C++中的一样:函数不可能返回局部变量的引用,由于局部变量保存在函数的栈空间中,函数调用结束后,栈被销毁。不能够对局部变量进行引用了。

    将a传递给函数fff后。a被改变了。说明进行了引用传递;函数fff的返回值赋给b。对b的改动也会影响到a,说明返回值也是进行的引用传递(只是这里返回的可不是局部变量了)。


    另外,字典还有自己的copy方法。但没有deepcopy方法。其copy方法和上面的copy模块中的copy方法一样,也是实现的浅拷贝。



    另一点:对于一般变量,假设想达到引用传递的效果,怎么办呢?python标准库中并没有提供类似C++中专门的引用或指针的机制,要实现函数内部对传入变量的改动有两种途径:

    1、通过函数返回值又一次赋值变量。

    2、将变量封装在列表中在传给函数。


    最后一点:把一个类的对象传递给函数的时候,类似引用传递,在函数内部改动类的变量。会真正改变其值。见下例:

    class TestClass(object):
        val1 = 100  #类变量
        
        def __init__(self):
            self.val2 = 200  #成员变量
        
    
    def change(obj):
        obj.val2 = 5555
        obj.val1 = 6666
    
    if __name__ == '__main__':    
        
        inst0 = TestClass()
        print '$$$ ',inst0.val1 #100
        print '$$$ ',inst0.val2 #200
        
        change(inst0)
        
        print '*** ',inst0.val1 #6666
        print '*** ',inst0.val2 #5555


  • 相关阅读:
    最大子数组问题(分治策略实现)
    Solving the Detached Many-to-Many Problem with the Entity Framework
    Working With Entity Framework Detached Objects
    Attaching detached POCO to EF DbContext
    如何获取qq空间最近访问人列表
    Health Monitoring in ASP.NET 2.0
    problem with displaying the markers on Google maps
    WebMatrix Database.Open… Close() and Dispose()
    Accessing and Updating Data in ASP.NET: Retrieving XML Data with XmlDataSource Control
    Create web setup project that has crystal reports and sql script run manually on client system
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5352330.html
Copyright © 2011-2022 走看看