2015-11-24 2 views
2

Мне нужно руководствоваться тем, как правильно настроить это для того, что я пытаюсь сделать. У меня есть класс под названием «Атрибут-блок», который я буду использовать для создания 3 или 4 блоков блока атрибутов. Как видно ниже ..., создавая новую копию класса python каждый раз, когда он называется

class AttributeBlock(): 
    def __init__(self, key, label, isClosed, isRequired, attributes): 
     self.key = key 
     self.label = label 
     self.isClosed = isClosed 
     self.isRequired = isRequired 
     self.attributes = attributes if attributes is not None else {} 

3 attributeBlock объекты

AttributeBlock(
    key="Sphere", 
    isRequired=True, 
    attributes=[ 
     ''' Other class objects ''' 
     BoolProperty("ishidden", False, "Hidden"), 
    ] 
) 

AttributeBlock(
    key="Box", 
    isRequired=True, 
    attributes=[ 
     ''' Other class objects ''' 
     BoolProperty("ishidden", True, "Hidden"), 
    ] 
) 

AttributeBlock(
    key="Circle", 
    isRequired=False, 
    attributes=[ 
     ''' Other class objects ''' 
     BoolProperty("ishidden", True, "Hidden"), 
    ] 
) 

Что я тогда хочу сделать, это иметь возможность добавить один из этих AttributeBlocks на объект, убедившись, что, когда он добавил, его новый экземпляр AttributeBlock, поэтому его объекты вспомогательных атрибутов являются новыми экземплярами.

Это объект, в который я буду добавлять свои блоки атрибутов.

class ToyBox(): 
    def __init__(self, name="", attributes=[]): 
     self.name = name 
     self.attributes = attributes[:] 

newToyBox = ToyBox() 
newToyBox.name = "Jimmy" 

псевдокод

def add_attribute_block(toybox = None, key = ""): 
    if an AttributeBlock with the matching key exists: 
     add it to toybox.attributes 

add_attribute_block(newToyBox, "Box") 

print newToyBox 
>> 
ToyBox 
name="Jimmy" 
attributes=[ 
    AttributeBlock(
     key="Box", 
     isRequired=True, 
     attributes=[ 
      BoolProperty("ishidden", True, "Hidden"), 
     ] 
    ), 
    AttributeBlock(
     key="Sphere", 
     isRequired=True, 
     attributes=[ 
      BoolProperty("ishidden", True, "Hidden"), 
     ] 
    ) 
] 

ответ

1

Если вы хотите автоматически отслеживать все созданные объекты AttributeBlock, вы можете использовать атрибут класса:

class AttributeBlock(): 
    objects = [] 
    def __init__(self, key, label, isClosed, isRequired, attributes): 
     self.key = key 
     self.label = label 
     self.isClosed = isClosed 
     self.isRequired = isRequired 
     self.attributes = attributes if attributes is not None else {} 
     self.objects.append(self) 

Как только это будет сделано, add_attribute может стать:

def add_attribute_block(toybox = None, key = ""): 
    if toybox is not None: 
     for obj in AttributeBlock.objects: 
      if obj.key == key: 
       toybox.attributes.append(obj) 
       break 

Вы можете также использовать отображение вместо списка для атрибута класса:

class AttributeBlock(): 
    objects = {] 
    def __init__(self, key, label, isClosed, isRequired, attributes): 
     if key in self.objects: 
      # raise a custom exception 
     ... 
     self.objects[key] = self 

Тогда вы можете просто использовать :

def add_attribute_block(toybox = None, key = ""): 
    if toybox is not None: 
     if key in AttributeBlock.objects: 
      toybox.attributes.append(AttributeBlock.objects[key]) 

Если вы хотите чтобы поместить копию объектов списка в ToyBox, вы должны изменить метод создания, чтобы позволить не помещать эту копию в глобальный список. В этом случае код станет:

class AttributeBlock(): 
    objects = {} 
    dummy = {} 
    def __init__(self, key, label, isClosed, isRequired, 
      attributes, glob = None): 
     if glob is None: 
      glob = self.objects 
     if key in glob: 
      raise ValueError(str(key) + " already exists") 
     self.key = key 
     self.label = label 
     self.isClosed = isClosed 
     self.isRequired = isRequired 
     self.attributes = attributes if attributes is not None else {} 
     if glob is not self.dummy: 
      glob[key] = self 
    def copy(self): 
     return AttributeBlock(self.key, self.label, self.isClosed, 
         self.isRequired, self.attributes[:], 
         self.dummy) 

с фиктивным объектом класса, который позволит не хранить вновь созданный объект в любом контейнере, и дополнительный glob параметром, который позволяет хранить его во внешнем Dict. Также обратите внимание на метод copy, который точно использует dummy.

add_attribute_block становится:

def add_attribute_block(toybox = None, key = "", glob = None): 
    if glob is None: 
     glob = AttributeBlock.objects 
    if toybox is not None: 
     if key in glob: 
      toybox.attributes.append(AttributeBlock.objects[key].copy()) 

с использованием метода копирования для хранения в Toybox, копию исходного объекта, который не хранится в глобальном контейнере.

+0

Это интересный подход. это хорошая практика или я должен создать более глобальную переменную, которая хранит все блоки атрибутов – JokerMartini

+0

, - это их проблемы, о которых я должен знать при выполнении этого метода? похоже на отличное решение – JokerMartini

+0

@JokerMartini: нет общего ответа. Если вы хотите отслеживать каждый атрибут AttributeBlock, интересен атрибут класса. Если вы хотите вместо этого иметь несколько независимых списков (подумайте о студентах в университете, что, если вы позже захотите иметь дело с разными университетами ...), вам лучше иметь внешний список и передать его в конструкторе. Как это часто бывает, это зависит от фактического использования. –

1

Если вы хотите, чтобы убедиться, что экземпляр Атрибут добавлен в ваш Toybox является копией, самый простой способ заключается в использовании standard copy module

import copy 
... 
class ToyBox(object): 
    ... 
    def add_attribute(self, attribute): 
     self.attributes.append(copy.deepcopy(attribute)) 
+0

Если это правда, как я затем настраиваю объекты AttributeBlock, чтобы затем создать функцию для добавления? – JokerMartini

+0

Не уверен, что я понимаю, о чем вы спрашиваете. Функция copy.deepcopy() не требует, чтобы для него был настроен класс объекта. copy.deepcopy (x) сделает копию объекта x независимо от его класса. –

1

Если я правильно понял, вы хотите, чтобы каждый экземпляр ToyBox содержал список экземпляров AttributeBlock, не проверяя, что другой такой объект с еще не указан в списке.

class AttributeBlock(): 
    def __init__(self, key): # demo, add the other parameters/attrs 
     self.key = key 
    def __str__(self): 
     return self.key # add the other parameters/attrs 

class ToyBox(object): 
    def __init__(self): 
     self.attributes = [] 

    def add_attr(self, a): 
     gen = (attr for attr in self.attributes if attr.key == a.key) 
     try: 
      next(gen) 
     except StopIteration: 
      self.attributes.append(a) 

    def __str__(self): 
     return ','.join(map(str,self.attributes)) 

Так что теперь мы можем сделать

>>> toy = ToyBox() 
>>> toy.add_attr(AttributeBlock("Box")) 
>>> toy.add_attr(AttributeBlock("Sphere")) 
>>> toy.add_attr(AttributeBlock("Box")) 
>>> print toy 
Box,Sphere 

Как вы заметили, это имеет смысл сделать add_attribute функция метод экземпляра ToyBox

Кстати, в случае, если количество объектов в attributes список большой, лучше использовать словарь:

class ToyBox(object): 
    def __init__(self): 
     self.attributes = dict() 

    def add_attr(self, a): 
     if a.key not in self.attributes: 
      self.attributes[a.key] = a 

    def __str__(self): 
     return ','.join(map(str,self.attributes.values())) 

Примечание: в случае, если вы хотите сохранить порядок добавления объектов, используйте OrderedDict вместо

+0

вы на правильном пути. Когда я создаю все мои attritubeBlocks, где я их храню. Я только хочу создать их один раз, когда инструмент запускается впервые.Должен ли я делать то, что предлагает Серый Балеста ниже? – JokerMartini

+0

они хранятся в списке экземпляра ToyBox. См. Примеры в моем редактировании, нет необходимости отслеживать их в переменной – Pynchia

1

Поместите все свои блоки атрибутов в список.

blocks = [] 

// add your AttributeBlocks to this list 
blocks.append(block1) 
blocks.append(block2) 
blocks.append(block3) 

Тогда это легко.

def add_attribute_block(toybox, key): 
    #loop over list of blocks and find the block with that key 
    for block in blocks: 
     if block.key == key: 
      #only add it to the toybox if its not already in there 
      if not any(key in l.key for l in toybox.attributes): 
       toybox.attributes.append(block) 
       break 

Примечание:

l.key for l in toybox.attributes список понимание и дает вам список всех ключей.

any(key in l.key for l in toybox.attributes)True если key есть в этом списке.

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