首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >每次调用python类时创建一个新副本

每次调用python类时创建一个新副本
EN

Stack Overflow用户
提问于 2015-11-24 14:15:40
回答 4查看 111关注 0票数 2

我需要一些指导,如何设置正确的这是我要做的。我有一个名为Attribute块的类,然后我将使用它来创建3或4个属性块对象。如下所示..。

代码语言:javascript
复制
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对象

代码语言:javascript
复制
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的一个新实例,因此它的子属性对象是新的实例。

这是我将添加属性块的对象。

代码语言:javascript
复制
class ToyBox():
    def __init__(self, name="", attributes=[]):
        self.name = name
        self.attributes = attributes[:]

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

伪码

代码语言:javascript
复制
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"),
        ]
    )
]
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-11-24 15:00:31

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

代码语言:javascript
复制
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可能变成:

代码语言:javascript
复制
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属性使用映射而不是列表:

代码语言:javascript
复制
class AttributeBlock():
    objects = {]
    def __init__(self, key, label, isClosed, isRequired, attributes):
        if key in self.objects:
            # raise a custom exception
        ...
        self.objects[key] = self

然后,您可以简单地使用:

代码语言:javascript
复制
def add_attribute_block(toybox = None, key = "" ):
    if toybox is not None:
        if key in AttributeBlock.objects:
            toybox.attributes.append(AttributeBlock.objects[key])

如果要在ToyBox中放置列表对象的副本,则必须更改创建方法以允许不将该副本放到全局列表中。在这种情况下,守则将成为:

代码语言:javascript
复制
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)

使用一个不允许在任何容器中存储新创建的对象的虚拟类对象,以及一个允许将其存储在外部dict中的可选glob参数。还要注意copy方法,它精确地使用了dummy

add_attribute_block变成:

代码语言:javascript
复制
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中存储未存储在全局容器中的原始对象的副本。

票数 1
EN

Stack Overflow用户

发布于 2015-11-24 14:36:33

如果要确保添加到ToyBox中的属性实例是副本,最简单的方法是使用标准复制模块

代码语言:javascript
复制
import copy
...
class ToyBox(object):
    ...
    def add_attribute(self, attribute):
        self.attributes.append(copy.deepcopy(attribute))
票数 1
EN

Stack Overflow用户

发布于 2015-11-24 15:06:39

如果我正确理解,您希望每个ToyBox实例包含一个AttributeBlock实例列表,检查列表中还没有其他同名的对象。

代码语言:javascript
复制
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))

所以现在我们可以

代码语言:javascript
复制
>>> 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列表中的对象数量很大,最好使用字典:

代码语言:javascript
复制
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代替

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33895930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档