python在使用deepcopy时将对象添加到变量

时间:2015-11-30 14:30:22

标签: python

我有几个问题。请记住,我需要使用深层复制,因为我的课程将在复杂性方面进行扩展。

  • 当我进行深层复制时,有没有办法让它达不到递归限制?
  • 当我预先形成深层副本时,我希望将新副本附加到NODES变量,就像在 init 中一样?
import copy

# Global
NODES = []

# Classes
class Node(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

class Truck(Node):
    def __init__(self, name="", age=0):
        super(Truck, self).__init__(name=name, age=age)
        NODES.append(self)

class Car(Node):
    def __init__(self, name="", age=0):
        super(Car, self).__init__(name=name, age=age)
        NODES.append(self)

    def __deepcopy__(self, memo):
        print '__deepcopy__(%s)' % str(memo)
        return Car(copy.deepcopy(self, memo))


Truck( name="Tonka Truck")
Truck( name="Monster Truck")
Truck( name="Pickup Truck")
car = Car( name="Oldsmobile Car")
car.age = 55
new_car = copy.deepcopy( car )

type_name = "Car"
cars = [x for x in NODES if type(x).__name__ == type_name]
print cars

print "NODES:"
for node in NODES:
    print "\t", node.name, node.age

1 个答案:

答案 0 :(得分:2)

首先,你真的应该使用defaultdict玩具。它只是满足这个要求如果超类不存在,它会添加并附加对象。所以,让我们一起去

Toys = collections.defaultdict(list)

如果您不想使用copy.deepcopy,只需将Node.__init__方法更改为:

class Node(object):
    def __init__(self, name, superclass):
        self.name = name
        self.superclass = superclass
        Toys[superclass].append(self)

创建新卡车时,它可以正常工作:

t = truck()
Toys['Trucks'][-1] is t

给出了真的

不幸的是,deepcopy使用了一种特殊的构造方案,并绕过__init__

但是__init__无法做到,只需致电__new__来帮助......

__new__是一个较低级别的特殊方法,称为类方法,用于在调用__init__之前创建对象。即使deepcopy创建的对象也是使用__new__创建的。因为它是一个类方法,你只需要声明超类名称(BTW超类是另一种动物而你真的应该使用不同的名称......)作为class attribute。

您的代码变为:

import copy
import collections

# Globals
Toys = collections.defaultdict(list)

class Node(object):
    def __new__(cls):
        obj = super(Node, cls).__new__(cls)
        superclass = cls.superclass
        Toys[superclass].append(obj)
        return obj

    def __init__(self, name=""):
        self.name = name

class Truck(Node):
    superclass = "Trucks"

class Car(Node):
    superclass = "Boats"

class Boat(Node):
    superclass = "Nodes"

class Plane(Node):
    superclass = "Planes"


t = Truck()
t.name = "Tonka Truck"
print Toys
t2 = copy.deepcopy( t )
print t, t2, Toys

使用此输出:

defaultdict(<type 'list'>, {'Trucks': [<__main__.Truck object at 0x0000000002D71A20>]})
<__main__.Truck object at 0x0000000002D71A20> <__main__.Truck object at 0x0000000002D71B70> defaultdict(<type 'list'>, {'Trucks': [<__main__.Truck object at 0x0000000002D71A20>, <__main__.Truck object at 0x0000000002D71B70>]})

证明:

  • Trucks列表已自动添加到Toys
  • t创建为Truck(),已正确添加到Toys['Trucks']
  • t2创建deepcopy已正确添加到Toys['Trucks']

您现在只需更改为superclass名称即可接受此代码......