2012-07-20 59 views
4

在以下代码:力蟒子类的init使用子类变量,而不是父类

class A(object): 
    VALUE = 1 
    def __init__(self, value=VALUE): 
    self.value = value 

class B(A): 
    VALUE = 2 

我期望B()值应等于2,但是:

B().value = 1 

有一种优雅的方式来定义一个类层次结构,其中子类可以只是声明,他们希望重写,并让他们为实例变量的默认值类变量?我仍然希望允许这些在每个实例级别上进行更改,例如。

b = B(value=3) 

回答

10

这是另一个default arguments的问题。重点是当你编写的时候

def foo(value=VALUE): 

函数内部的代码被编译成一个函数对象。这是这个时间 - 不是在通话时! - 存储默认参数。所以,你的时间已经确定B为时已晚:中foo默认值已经被设置和改变VALUE不会有任何效果。

如果这似乎是一个奇怪的事情,假设foo是一个全球性的功能:

default = 3 
def foo(x=default): pass 

那么任何其他代码,任何地方,可以通过做

global default 
default = 4 

搞砸foo这无疑是同样令人困惑。


要强制查找在运行时做了不编译的时候,你需要把它们功能:

def foo(value=None): 
    self.value = self.VALUE if value is None else value 

或(不完全一样,但是更漂亮)

self.value = value or self.VALUE 

(这是不同的,因为它将把任何“falsy”值作为前哨 - 也就是说,0[]{}等将全部由VALUE覆盖)


编辑:@mgilson指出,这样做的另一种方式:

def foo(**kwargs): 
    self.value = kwargs.get("value", self.VALUE) 

这是因为它不要求整洁你做一个标记值(如Noneobject(),但它确实改变foo相当根本的参数规格,因为现在它会接受任意关键字参数。你的来电。

+0

与津贴做正确的唯一方法:

可以按如下步骤写出来。 – 2012-07-20 14:44:29

+3

@JonasWielicki:如果允许None,你可以使用一个哨兵NOT_VALUE = object()。你不需要'** kwargs' – jfs 2012-07-20 14:45:26

+0

@ J.F.Sebastian哦不错。 – 2012-07-20 14:46:04

1

不应该在func声明行中定义默认值,否则,当python读取此行时,默认值将被重点关注,无论您稍后更改VALUE值,都不会更改默认值。对于`None`使用`** kwargs`虽然检查中kwargs``“值”

class A: 
    VALUE = 1 
    def __init__(self, value=None): 
     if value is None: 
      value = self.VALUE 
     self.value = value 

class B(A): 
    VALUE = 2 

print(A().value) 
print(B().value) 
相关问题