通过实例方法对类属性引用的对象进行变换

时间:2015-03-03 14:37:42

标签: python

这是一个由两部分组成的查询,它广泛地涉及引用可变和不可变对象的类属性,以及如何在代码设计中处理它们。我已经抽象出细节以提供下面的示例课程。

在此示例中,该类设计用于两个实例,通过实例方法可以访问引用可变对象(在本例中为列表)的类属性,每个实例都可以“获取”(通过改变对象)将此对象的元素放入其自己的实例属性中(通过改变它引用的对象)。如果一个实例“获取”类属性的元素,那么该元素随后对另一个实例不可用,这是我希望实现的效果。我发现这是避免使用类方法的一种方便方法,但这是不好的做法吗?

此外,在此示例中,还有一个类方法,它根据实例属性的状态将不可变对象(在本例中为布尔值)重新分配给类属性。我可以通过使用一个类方法来实现这一点,其中cls作为第一个参数,self作为第二个参数,但我不确定这是否正确。另一方面,也许这就是我应该如何处理这个查询的第一部分?

class Foo(object):
    mutable_attr = ['1', '2']
    immutable_attr = False

    def __init__(self):
        self.instance_attr = []

    def change_mutable(self):
        self.instance_attr.append(self.mutable_attr[0])
        self.mutable_attr.remove(self.mutable_attr[0])

    @classmethod
    def change_immutable(cls, self):
        if len(self.instance_attr) == 1:
            cls.immutable_attr = True


eggs = Foo()
spam = Foo()

2 个答案:

答案 0 :(得分:0)

如果你想要一个类级别的属性(就像你说的那样,#34;可见"对于这个类的所有实例),使用类似你所显示的类方法就可以了。这主要是一个风格问题,这里没有明确的答案。所以你展示的很好。

我只想指出,您不必使用课程方法来实现目标。为了实现你的目标,这也很完美(在我看来,更标准):

class Foo(object):

    # ... same as it ever was ... 

    def change_immutable(self):
        """If instance has list length of 1, change immutable_attr for all insts."""
        if len(self.instance_attr) == 1:
            type(self).immutable_attr = True

甚至:

    def change_immutable(self):
        """If instance has list length of 1, change immutable_attr for all insts."""
        if len(self.instance_attr) == 1:
            Foo.immutable_attr = True

如果这是你想做的。主要的一点是,您不必强制使用类方法来获取/设置类级属性。

type内置函数(https://docs.python.org/2/library/functions.html#type)只返回实例的类。对于新样式类(现在大多数类,最终来自对象的类)类型(self)与self.__class__相同,但使用type是访问对象类型的更惯用的方式。

当您想要编写获取对象最终类型的代码时,即使它是子类,也可以使用type。这可能是也可能不是你想做的。例如,假设你有这个:

class Baz(Foo): 
    pass

bazzer = Baz()
bazzer.change_mutable()
bazzer.change_immutable()

然后是代码:

type(self).immutable_attr = True

更改immutable_attr课程的Baz,而不是Foo课程。这可能是也可能不是你想要的 - 只要知道只有来自Baz的对象才能看到这一点。如果您想让{em>所有后代Foo可见,那么更合适的代码是:

Foo.immutable_attr = True

希望这会有所帮助 - 这个问题很好,但有点开放。同样,主要的一点是你不会被迫使用类方法来设置/获取类attrs - 但不是没有任何错误:)

最后请注意你第一次写它的方式:

@classmethod
def change_immutable(cls, self):
    if len(self.instance_attr) == 1:
        cls.immutable_attr = True

就像在做:

type(self).immutable_attr = True

方式,因为cls变量不一定是Foo,如果它是子类的。如果您确定要为 Foo的所有实例设置它,那么只需直接设置Foo类:

Foo.immutable_attr = True

是要走的路。

答案 1 :(得分:0)

这是一种可能性:

class Foo(object):
    __mutable_attr = ['1', '2']
    __immutable_attr = False

    def __init__(self):
        self.instance_attr = []

    def change_mutable(self):
        self.instance_attr.append(self.__class__.__mutable_attr.pop(0))
        if len(self.instance_attr) == 1:
            self.__class__.__immutable_attr = True

    @property
    def immutable_attr(self):
        return self.__class__.__immutable_attr

所以一点点解释:
1.我更难以从外部访问类属性,以通过在前面添加双下划线来保护它们免受意外更改。
2.我在一行中pop()append() 3.如果符合条件,我在修改__immutable_attr后立即设置__mutable_attr的值 4.我将immutable_attr作为只读属性公开,以便提供检查其价值的简便方法 5.我正在使用self.__class__来访问实例的类 - 它比type(self)更具可读性,并且可以直接访问带有双下划线的属性。