python类defau的临时更改

2024-04-25 09:35:27 发布

您现在位置: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


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)。有进一步的想法或改进吗?你知道吗

提前谢谢


Tags: thenameselfnonedefaultifvalueversion
2条回答

在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_DEFAULT。你知道吗

下面是你如何解决这个问题的。你知道吗

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

无论何时需要默认值以外的值,都可以将其作为关键字value提供。你知道吗

或者,如果您想解决易变性bug,但仍然使用其他解决方案,则需要copy。你知道吗

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()

c1c2c3value[1,2,3]
c4c5c6具有value[100,12]。你知道吗

如果将其他参数传递给C初始化器,则可以向make_cfactory和/或lambda函数添加参数。你知道吗

相关问题 更多 >