Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
每次创建python类的新副本时';这叫什么_Python_Class_Oop - Fatal编程技术网

每次创建python类的新副本时';这叫什么

每次创建python类的新副本时';这叫什么,python,class,oop,Python,Class,Oop,我需要一些关于如何为我正在尝试的事情正确设置的指导。 我有一个名为attributeblock的类,然后我将使用它创建3或4个属性块对象。如下图所示 class AttributeBlock(): def __init__(self, key, label, isClosed, isRequired, attributes): self.key = key self.label = label self.isClosed = isClose

我需要一些关于如何为我正在尝试的事情正确设置的指导。 我有一个名为attributeblock的类,然后我将使用它创建3或4个属性块对象。如下图所示

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(
    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"),
    ]
)
然后我想做的是能够将这些AttributeBlock中的一个添加到对象中,确保在添加时,它是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"),
        ]
    )
]

如果要确保添加到ToyBox的属性实例是副本,最简单的方法是使用


如果要自动跟踪所有创建的
AttributeBlock
对象,可以使用class属性:

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)
class AttributeBlock():
    objects = {]
    def __init__(self, key, label, isClosed, isRequired, attributes):
        if key in self.objects:
            # raise a custom exception
        ...
        self.objects[key] = self
完成此操作后,
add_属性
可能会变成:

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 = {}
    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)
还可以使用映射而不是类属性的列表:

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)
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
,则必须更改创建方法以允许不将该副本放入全局列表。在这种情况下,代码将变成:

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 = {}
    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

添加属性块
变为:

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())

使用copy方法在ToyBox中存储未存储在全局容器中的原始对象的副本。

如果我理解正确,您希望每个
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_属性
函数作为
ToyBox

顺便说一句,如果
属性
列表中的对象数量很大,最好使用字典:

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()))

注意:如果要保持添加对象的顺序,请改用

将所有属性块放入列表中

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
注:

toybox.attributes中l的l.key是一个列表理解,为您提供所有键的列表


any(在toybox.attributes中为l输入l.key)
如果
key
在该列表中,则返回
True

如果这是真的,我如何设置AttributeBlock对象,以便创建用于添加的函数?我不确定是否理解您的要求。函数不需要为其设置对象的类。deepcopy(x)将复制对象x,不管它是什么类。这是一种有趣的方法。这是一个好的做法,还是我应该创建一个更全局的变量来存储所有属性块?在使用此方法时,我应该注意哪些问题?看起来是个好主意solution@JokerMartini:没有一般答案。如果要跟踪每个
属性block
,则类属性很有趣。如果你想拥有多个独立的列表(想想一所大学的学生,如果你以后想与不同的大学打交道会怎么样…),你最好有一个外部列表并将其传递给构造函数。就像经常发生的那样,这取决于实际的用例。在我的例子中,我只需要一个包含所有创建的AttributeBlock的列表。如果是这样的话,那么你的解决方案看起来会工作得很好,对吗?我还注意到你在做一个直接的附加操作,我不需要做一个深度复制吗?你的思路是正确的。当我创建所有属性块时,我将它们存储在何处。我只想在工具首次启动时创建它们一次。我应该按照Serge Ballesta下面的建议做吗?它们存储在ToyBox实例的列表中。请参见我的编辑中的示例,无需在变量中跟踪它们