python类默认值的临时更改

python类默认值的临时更改,python,default,temporary,Python,Default,Temporary,我想临时更改类的默认值。我想到了一些想法: class C(object): VALUE_DEFAULT = [1, 2, 3] def __init__(self, value=None): if value is None: value = self.VALUE_DEFAULT self._value = value @property def value(self): return s

我想临时更改类的默认值。我想到了一些想法:

class C(object):
    VALUE_DEFAULT = [1, 2, 3]
    def __init__(self, value=None):
        if value is None:
            value = self.VALUE_DEFAULT
        self._value = value

    @property
    def value(self):
        return self._value


print("Initial default:", C().value)

"""
1) Repetitious version that makes code unclear if multiple
instances should be instantiated or the default should not be used.
"""
print("Changed default manually:", C(value=[0, 2, 4]).value)

"""
2) dangerously hard coded version
"""
C.VALUE_DEFAULT = [0, 2, 4]
print("Changed default by changing the default constant:", C().value)
C.VALUE_DEFAULT = [1, 2, 3]


"""
3) possibly more pythonic version
still this version seems hacky
"""
from contextlib import contextmanager

@contextmanager
def tmp_default(cls, name, value):
    old_val = getattr(cls, name)
    setattr(cls, name, value)
    yield
    setattr(cls, name, old_val)

with tmp_default(C, "VALUE_DEFAULT", [0, 2, 4]):
    print("Changed default with contextmanager:", C().value)

print("Restored the default again:", C().value)
从以上的可能性来看,我强烈倾向于3)。有进一步的想法或改进吗


提前感谢

在Python中使用可选的关键字参数应该是这样做的。不过,我想指出您的代码存在一个问题

class C(object):
    VALUE_DEFAULT = [1, 2, 3]
    def __init__(self, value=None):
        if value is None:
            value = self.VALUE_DEFAULT
        self._value = value

    @property
    def value(self):
        return self._value

c1 = C()
c2 = C()
c1.value [0] = 10
c2.value # [10, 2, 3]
由于您将相同的可变列表指定为默认值,因此更新
c1.value
将更新
C.value\u默认值

以下是您如何解决此问题的方法

class C(object):
    def __init__(self, value=None):
        # create a new array everytime
        self._value = [1, 2, 3] if value is None else value

    @property
    def value(self):
        return self._value
当您需要默认值以外的值时,可以将其作为关键字
提供

或者,如果您想解决易变性bug,但仍然使用其他解决方案,则需要
复制

import copy

class C(object):
    VALUE_DEFAULT = [1, 2, 3]
    def __init__(self, value=None):
        if value is None:
            value = copy.copy(self.VALUE_DEFAULT)
        self._value = value

    @property
    def value(self):
        return self._value

这是我的建议,涉及工厂

def make_cfactory(argument):
    return lambda : C(argument.copy())
我想用参数
[1,2,3]
实例化一堆
C
,但我不想继续键入
[1,2,3]
。我没有使用
C(…)
来实例化它们,而是使用工厂来实例化它们

cfac = make_cfactory([1,2,3])
c1 = cfac()
c2 = cfac()
c3 = cfac()
cfac = make_cfactory([100,12])
c4 = cfac()
c5 = cfac()
c6 = cfac()
c1
c2
c3
具有
[1,2,3]
c4
c5
c6
具有
[100,12]


如果将其他参数传递给
C
初始化器,则可以将参数添加到
make\u cfactory
和/或lambda函数。

为什么不在创建此类实例时简单地设置所需的值呢?似乎这对工厂更有意义。@Haleemur我需要创建实例的加载。所以变体1非常重复。@khelwood:好主意,不过,我需要多次更改默认值。因此,我最终会有100家工厂,或者再次提出一个论点,这将使创建工厂变得多余,甚至更加混乱。拥有数百家工厂不会花费任何成本。谢谢你指出了可变性问题。你的答案是我的方法1——当移除易变性问题时。我认为方法1是最具python风格的。但如果不适合您,请随时等待另一种方法。@Daniel Böckenhoff我还为您的其他方法添加了一种解决可变性问题的方法