Reputation: 6147
I need some guidance on how to set this up correctly for what I'm trying to do. I have a class called Attribute Block which I'll then use to create 3 or 4 Attribute block Objects. As seen below...
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 objects
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"),
]
)
What I then want to do is be able to add one of these AttributeBlocks to an Object, making sure when it's added, its a new instance of the AttributeBlock so its sub attribute objects are new instances.
This is the object I will add my attribute blocks to.
class ToyBox():
def __init__(self, name="", attributes=[]):
self.name = name
self.attributes = attributes[:]
newToyBox = ToyBox()
newToyBox.name = "Jimmy"
pseudo code
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"),
]
)
]
Upvotes: 2
Views: 113
Reputation: 148890
If you want to automatically keep track of all created AttributeBlock
objects, you could use a class attribute:
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)
Once this is done, add_attribute
could become:
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
You could also use a mapping instead of a list for the class attribute:
class AttributeBlock():
objects = {]
def __init__(self, key, label, isClosed, isRequired, attributes):
if key in self.objects:
# raise a custom exception
...
self.objects[key] = self
Then you can simply use:
def add_attribute_block(toybox = None, key = "" ):
if toybox is not None:
if key in AttributeBlock.objects:
toybox.attributes.append(AttributeBlock.objects[key])
If you want to put a copy of the objects of the list in the ToyBox
, you must change the creation method to allow to not put that copy in the global list. In that case, code would become:
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)
with a dummy class object that allow to not store the newly created object in any container, and an optional glob
parameter that allows to store it in an external dict. Also notice the copy
method that precisely uses dummy
.
add_attribute_block
becomes:
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())
using the copy method to store in the ToyBox, a copy of the original object that is not stored in the global container.
Upvotes: 1
Reputation: 11590
If I understand correctly, you want the each ToyBox
instance to contain a list of AttributeBlock
instances, checking no other such object with the
same name is present in the list yet.
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))
So now we can do
>>> toy = ToyBox()
>>> toy.add_attr(AttributeBlock("Box"))
>>> toy.add_attr(AttributeBlock("Sphere"))
>>> toy.add_attr(AttributeBlock("Box"))
>>> print toy
Box,Sphere
As you notice, it makes sense to make the add_attribute
function an instance method of ToyBox
BTW, in case the number of objects in the attributes
list is large, it's better to use a dictionary:
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()))
Note: in case you want to keep the order in which the objects are added, use an OrderedDict instead
Upvotes: 1
Reputation: 1066
Put all your attribute blocks in a list.
blocks = []
// add your AttributeBlocks to this list
blocks.append(block1)
blocks.append(block2)
blocks.append(block3)
Then it's easy.
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
Note:
l.key for l in toybox.attributes
is a list comprehension and gives you a list of all keys.
any(key in l.key for l in toybox.attributes)
returns True
if key
is in that list.
Upvotes: 1
Reputation: 1330
If you want to make sure the Attribute instance added to your ToyBox is a copy, the easiest way is to use the standard copy module
import copy
...
class ToyBox(object):
...
def add_attribute(self, attribute):
self.attributes.append(copy.deepcopy(attribute))
Upvotes: 1