[英]Force python subclass init to use subclass variables, not parent class
In the following code: 在以下代码中:
class A(object):
VALUE = 1
def __init__(self, value=VALUE):
self.value = value
class B(A):
VALUE = 2
i'd expect that B().value should be equal to 2, however: 我希望B()。值应该等于2,但是:
B().value = 1
Is there an elegant way to define a class hierarchy where child classes can just declare class variables they want to override and have them be defaults for the instance variables? 是否有一种优雅的方法来定义一个类层次结构,其中子类只能声明它们想要覆盖的类变量并使它们成为实例变量的默认值? I still want to allow for these to be changed on a per-instance level, eg. 我仍然希望允许在每个实例级别更改这些,例如。
b = B(value=3)
This is another default arguments question. 这是另一个默认参数问题。 The point is that when you write 关键是你写的时候
def foo(value=VALUE):
the code inside the function is compiled and made into a function object. 函数内部的代码被编译并成为一个函数对象。 It is at this time -- not at call time! 就在这个时候 - 而不是在通话时间! -- that the default arguments are stored. - 存储默认参数。 So by the time you have defined B
it is too late: the default value of foo
is already set and changing VALUE
won't have any effect. 因此,当您定义B
,为时已晚: foo
的默认值已经设置,更改VALUE
将不会产生任何影响。
If this seems a strange thing to do, suppose foo
was a global function: 如果这看起来很奇怪,假设foo
是一个全局函数:
default = 3
def foo(x=default): pass
Then any other code, anywhere, could screw up foo
by doing 然后任何其他代码,任何地方,可以搞砸了foo
global default
default = 4
This is arguably just as confusing. 这可以说是令人困惑的。
To force the lookups to be done at runtime not compile time, you need to put them inside the function: 要强制在运行时完成查找而不是编译时间,您需要将它们放在函数中:
def foo(value=None):
self.value = self.VALUE if value is None else value
or (not quite the same but prettier) 或(不完全相同但更漂亮)
self.value = value or self.VALUE
(This is different because it will treat any 'falsy' value as a sentinel -- that is, 0
, []
, {}
etc will all be overwritten by VALUE
.) (这是不同的,因为它将任何 'falsy'值视为哨兵 - 即0
, []
, {}
等都将被VALUE
覆盖。)
EDIT: @mgilson pointed out another way of doing this: 编辑:@mgilson指出了另一种方法:
def foo(**kwargs):
self.value = kwargs.get("value", self.VALUE)
This is neater in that it doesn't require you to make a sentinel value (like None
or object()
, but it does change the argument specification of foo
quite fundamentally since now it will accept arbitrary keyword arguments. Your call. 这更简洁,因为它不需要你创建一个sentinel值(如None
或object()
,但它确实从根本上改变了foo
的参数规范,因为现在它将接受任意关键字参数。你的调用。
The default value should not be define in the func declaration line, otherwise, when the python reads this line, the default value will be focused, and whatever you change the VALUE later, the default value will not be changed. 不应在func声明行中定义默认值,否则,当python读取此行时,默认值将被聚焦,无论您稍后更改VALUE,默认值都不会更改。
You could write it as follows: 您可以按如下方式编写它:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.