我是否应该像这样给我的类成员提供默认值:
class Foo:
num = 1
或者像这样?
class Foo:
def __init__(self):
self.num = 1
在this question中我发现在这两种情况下,
bar = Foo()
bar.num += 1
是一个定义良好的操作。
我知道第一个方法会给我一个类变量,而第二个不会。但是,如果我不需要类变量,而只需要为我的实例变量设置一个默认值,那么这两种方法是否一样好?或者他们中的一个比另一个更“蟒蛇”?
我注意到的一件事是,在Django教程中,they use the second method to declare Models.个人认为第二种方法更优雅,但我想知道什么是“标准”方法。
发布于 2010-04-21 17:02:25
扩展bp的答案,我想向您展示他所说的不可变类型是什么意思。
首先,这是可以的:
>>> class TestB():
... def __init__(self, attr=1):
... self.attr = attr
...
>>> a = TestB()
>>> b = TestB()
>>> a.attr = 2
>>> a.attr
2
>>> b.attr
1
然而,这只适用于不可变(不可改变)的类型。如果缺省值是可变的(意味着它可以被替换),那么就会发生这种情况:
>>> class Test():
... def __init__(self, attr=[]):
... self.attr = attr
...
>>> a = Test()
>>> b = Test()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[1]
>>>
请注意,a
和b
都有一个共享属性。这通常是不必要的。
当类型可变时,这是定义实例变量默认值的Pythonic方法:
>>> class TestC():
... def __init__(self, attr=None):
... if attr is None:
... attr = []
... self.attr = attr
...
>>> a = TestC()
>>> b = TestC()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[]
我的第一段代码之所以有效,是因为对于不可变类型,只要您需要,Python就会创建一个新的实例。如果您需要将1加到1,Python会为您创建一个新的2,因为旧的1是不能更改的。我相信,这主要是为了散列。
发布于 2010-04-21 16:35:26
使用类成员给出默认值效果很好,只要你只对不可变值小心。如果你试图用列表或字典来做这件事,那将是非常致命的。它还适用于实例属性是对类的引用的情况,只要缺省值为None即可。
我看到这种技术在repoze中得到了非常成功的应用,这是一个运行在Zope之上的框架。这样做的好处不仅在于,当您的类持久化到数据库时,只需要保存非默认属性,而且当您需要向模式中添加新字段时,所有现有对象都会看到具有默认值的新字段,而不需要实际更改存储的数据。
我发现它在更通用的编码中也能很好地工作,但它是一个风格问题。使用任何你最满意的东西。
发布于 2010-04-21 16:24:09
使用类成员作为实例变量的默认值并不是一个好主意,而且这是我第一次看到有人提到这个想法。它在您的示例中可以工作,但在许多情况下可能会失败。例如,如果值是可变的,在未修改的实例上改变它将改变默认值:
>>> class c:
... l = []
...
>>> x = c()
>>> y = c()
>>> x.l
[]
>>> y.l
[]
>>> x.l.append(10)
>>> y.l
[10]
>>> c.l
[10]
https://stackoverflow.com/questions/2681243
复制相似问题