python和常量中的可变对象

时间:2014-01-17 22:33:35

标签: python

我有一个包含数据作为属性的类,它有一个返回包含这些属性的元组的方法:

class myclass(object):
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c

    def tuple(self):
        return (self.a, self.b, self.c)

我将此类用作元组,其中可以通过属性名称修改/读取项(属性)。现在我想创建这个类的对象,这些对象将是常量并具有预定义的属性值,然后我可以将其分配给变量/可变对象,从而初始化此变量对象的属性以匹配常量对象,而在同时保留修改属性值的能力。例如,我想这样做:

constant_object = myclass(1,2,3)
variable_object = constant_object
variable_object.a = 999

现在当然这在python中不起作用,所以我想知道获得这种功能的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

import copy

class myclass(object):
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c

    def tuple(self):
        return (self.a, self.b, self.c)

constant_object = myclass(1,2,3)
variable_object = copy.deepcopy(constant_object)
variable_object.a = 999
print constant_object.a
print variable_object.a

输出:

1
999

答案 1 :(得分:1)

在这种情况下,深度复制并不是完全必要的,因为您设置tuple方法的方式

class myclass(object):
    def __init__(self,a,b,c):
        self.a = a
        self.b = b
        self.c = c

    def tuple(self):
        return (self.a, self.b, self.c)

constant_object = myclass(1,2,3)
variable_object = myclass(*constant_object.tuple())
variable_object.a = 999

>>> constant_object.a
1
>>> variable_object.a
999

通常(正如其他人所建议的那样),你想要深度复制。这会创建一个全新的对象,与被复制的对象无关。但是,鉴于您仅使用int s,深度复制是过度的。你最好做一个浅拷贝。事实上,在你已经拥有的对象的参数上调用类构造函数甚至可能更快,因为这些参数是int s。这就是我建议上面代码的原因。

答案 2 :(得分:1)

  

现在我想创建这个类的对象,它们是常量并具有预定义的属性值,然后我可以将其分配给变量/可变对象,从而初始化此变量对象的属性以匹配常量对象,

嗯,你不能拥有那个。 Python中的赋值不会初始化任何内容。它不会复制或创建任何内容。它只是给现有值一个新名称。

如果要初始化对象,在Python中执行此操作的方法是调用构造函数。

所以,使用现有代码:

new_object = myclass(old_object.a, old_object.b, old_object.c)

如果你看一下大多数内置和stdlib类,它会更方便。例如:

a = set([1, 2, 3])
b = set(a)

他们是如何做到的?简单。只需定义一个可以使用现有实例调用的__init__方法。 (在set的情况下,这是免费的,因为set可以使用任何可迭代进行初始化,set可以迭代。)

如果你不想放弃现有的设计,你需要一个非常笨拙的__init__,但它至少是可行的。也许这个:

_sentinel = object()
def __init__(myclass_or_a, b=_sentinel, c=_sentinel):
    if isinstance(a, myclass):
        self.a, self.b, self.c = myclass_or_a.a, myclass_or_a.b, myclass_or_a.c
    else:
        self.a, self.b, self.c = myclass_or_a, b, c

...加上一些错误处理,以检查第一种情况下的b is _sentinel,而不是另一种情况。


所以,不过你这样做了:

constant_object = myclass(1,2,3)
variable_object = myclass(constant_object)
variable_object.a = 999