2015-11-30 2 views
0

У меня есть несколько вопросов. Имейте в виду, что мне нужно использовать глубокую копию, поскольку мои классы будут расширяться по сложности.python добавить объект к переменной при использовании deepcopy

  • Есть ли способ сделать это не до предела рекурсии, когда я делаю глубокую копию?
  • Когда я создаю глубокую копию, я хочу, чтобы новая копия была добавлена ​​к переменной 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 
+0

Звучит как случай для метаклассов. Удачи, они смутили меня. – Holloway

+2

Почему вы не можете сделать первую часть этого в 'Node .__ init__'? К этому моменту у вас есть вся необходимая информация. –

+0

как бы я сделал часть 2, то? – JokerMartini

ответ

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 

дает True

К сожалению, deepcopy использует специальную схему строительства и обходит __init__ здесь.

Но когда __init__ не может сделать, просто позвоните __new__, чтобы помочь ...

__new__ является нижним специальным методом уровня вызывается как метод класса для создания объекта перед __init__ называется. И даже deepcopy созданных объектов создаются с __new__. Поскольку это метод класса, вам просто нужно объявить имена суперкласса (BTW a суперкласс - это другое животное, и вы действительно должны использовать другое имя ...) в качестве атрибута класса.

Вы код становится:

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 CREA Ted, как Truck(), как было добавлено в Toys['Trucks']
  • t2 создать с deepcopy, как было добавлено в Toys['Trucks']

Теперь вы просто должны изменить, чтобы superclass имя для этого кода, чтобы быть приемлемым ...

+0

только для того, чтобы быть ясным, вы говорите, что я не должен использовать «суперкласс», поскольку он уже используется в python как что-то еще? – JokerMartini

+0

почему use collections.defaultdict (list) over only empty [] или {} – JokerMartini

+0

Наконец, если я хочу, чтобы в любой момент был создан новый узел, чтобы получить новый графический интерфейс, где бы я его разместил? 'import uuid nodeID = uuid.uuid4()' – JokerMartini

Смежные вопросы