这是一个由两部分组成的查询,它广泛地涉及引用可变和不可变对象的类属性,以及如何在代码设计中处理它们。我已经抽象出细节以提供下面的示例课程。
在此示例中,该类设计用于两个实例,通过实例方法可以访问引用可变对象(在本例中为列表)的类属性,每个实例都可以“获取”(通过改变对象)将此对象的元素放入其自己的实例属性中(通过改变它引用的对象)。如果一个实例“获取”类属性的元素,那么该元素随后对另一个实例不可用,这是我希望实现的效果。我发现这是避免使用类方法的一种方便方法,但这是不好的做法吗?
此外,在此示例中,还有一个类方法,它根据实例属性的状态将不可变对象(在本例中为布尔值)重新分配给类属性。我可以通过使用一个类方法来实现这一点,其中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()
答案 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)
更具可读性,并且可以直接访问带有双下划线的属性。