Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在类中设置默认值_Python_Class_Default - Fatal编程技术网

Python 在类中设置默认值

Python 在类中设置默认值,python,class,default,Python,Class,Default,我正在用Python创建一个类,我不确定如何正确设置默认值。我的目标是为所有类实例设置默认值,这些值也可以由类方法修改。但是,我希望在调用方法后恢复初始默认值 我已经能够使它与下面显示的代码一起工作。它不是很“漂亮”,所以我怀疑有更好的方法来解决这个问题 类图: 定义初始(自我,**kwargs): self.default_attr={'a':1,'b':2,'c':3} 自我默认属性更新(kwargs) self.\u dict\u.update((k,v)表示self.default\u

我正在用Python创建一个类,我不确定如何正确设置默认值。我的目标是为所有类实例设置默认值,这些值也可以由类方法修改。但是,我希望在调用方法后恢复初始默认值

我已经能够使它与下面显示的代码一起工作。它不是很“漂亮”,所以我怀疑有更好的方法来解决这个问题

类图:
定义初始(自我,**kwargs):
self.default_attr={'a':1,'b':2,'c':3}
自我默认属性更新(kwargs)
self.\u dict\u.update((k,v)表示self.default\u attr.items()中的k,v)
def方法1(自身,**kwargs):
自我记录更新((k,v)用于kwargs.items()中的k,v)
####这个方法的代码在这里
#然后恢复初始默认值
self.\u dict\u.update((k,v)表示self.default\u attr.items()中的k,v)
当我使用这个类时,我会做一些类似于
my_instance=plots()
my_instance.method1()
my_instance.method1(b=5)
,和
my_instance.method1()
。第三次调用
method1
时,如果不在方法定义末尾重置默认值,
b
将为5,但我希望它再次为2

注意:上面的代码只是一个示例。真正的类有几十个默认值,将它们全部用作输入参数将被视为反模式


有关如何正确解决此问题的任何建议?

您可以使用类变量和属性来实现为所有类实例设置默认值的目标。可以直接修改实例值,并在调用方法后恢复初始默认值

考虑到“真实类有多个默认值”的上下文,您可以考虑的另一种方法是设置包含默认值的<强>配置文件< /强>,并使用此文件初始化或重置默认值。

下面是使用一个类变量的第一种方法的一个简短示例:

class Plots:

    _a = 1

    def __init__(self):
        self._a = None
        self.reset_default_values()

    def reset_default_values(self):
        self._a = Plots._a

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = value


plot = Plots()
print(plot.a)

plot.a = 42
print(plot.a)

plot.reset_default_values()
print(plot.a)
输出:

1
42
1

您可以使用上下文管理器或装饰器来应用和重置值,而无需在每个方法上键入相同的代码

我不想使用self.default\u attr,而是返回到以前的状态

使用装饰器,您可以获得:

def with_kwargs(fn):
    def inner(self, **kwargs):
        prev = self.__dict__.copy()
        try:
            self.__dict__.update(kwargs)
            ret = fn(self)
        finally:
            self.__dict__ = prev
        return ret
    return inner


class plots:
    a = 1
    b = 2
    c = 3

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    @with_kwargs
    def method1(self):
        # Code goes here

我认为这是个坏主意,至少建议不要对
图进行变异。您可以通过创建一个新对象并将其作为
self
传递给
method1
来实现这一点

class Transparent:
    pass


def with_kwargs(fn):
    def inner(self, **kwargs):
        new_self = Transparent()
        new_self.__dict__ = {**self.__dict__, **kwargs}
        return fn(new_self)
    return inner

有很多方法可以解决这个问题,但是如果您安装了Python3.7(或者安装了3.6和install),可能是一个很好的解决方案

首先,它允许您以可读且紧凑的方式定义默认值,还允许您需要的所有变异操作:

>>从数据类导入数据类
>>>@dataclass
... 类图:
...     a:int=1
...     b:int=2
...     c:int=3
...     
>>>p=Plots()#创建一个只有默认值的绘图
>>>p
图(a=1,b=2,c=3)
>>>p.a=-1#更新此绘图实例中的某些内容
>>>p
图(a=-1,b=2,c=3)
您还可以使用免费的选项定义默认工厂,而不是默认值。这可能还不是一个问题,但它避免了每个python程序员迟早会遇到的问题

最后但并非最不重要的一点是,在现有数据类的情况下,编写
重置
函数相当容易,因为它可以跟踪其
\uuuuuuu数据类\uuuuu字段\uuuu
属性中已有的所有默认值:

>>从数据类导入数据类,缺少
>>>@dataclass
... 类图:
...     a:int=1
...     b:int=2
...     c:int=3
... 
...     def重置(自):
...         对于名称,在self.\u dataclass\u fields\u.items()中输入字段:
...             如果field.default!=缺失:
...                 setattr(self、name、field.default)
...             其他:
...                 setattr(self、name、field.default\u factory())
...
>>>p=绘图(a=-1)#创建一个带有一些非默认值的绘图
>>>p
图(a=-1,b=2,c=3)
>>>p.reset()#对其调用reset可恢复预定义的默认值
>>>p
图(a=1,b=2,c=3)

因此,现在您可以编写一些函数
do_stuff(…)
,更新绘图实例中的字段,只要执行
reset()
,更改就不会持续

def\uuuu init\uuuuuu(self,a=1,b=2,c=3,**kwargs):
?至于
method1
,听起来它的
kwargs
有一个局部范围,那么为什么还要设置全局变量,然后在最后重置它们呢?只需将
kwargs
用作
method1
@中的局部变量,我想应该是该方法的代码会调用其他方法,并且他希望它们看到临时修改的属性。
mock
库提供了,您可以将其用作上下文管理器,然后
self.\uuu dict\uuuu.update((k,v)表示kwargs.items()中的k,v)
->
self.\uu dict\uuuu.update(kwargs)
@ReblochonMasque这是一个棘手的问题
patch.dict
,因为它更新数据而不是修补名称,在
mock
库中感觉至少有点不合适。但是在生产代码中使用
mock
会让我口齿不清,因此我会给出评论而不是答案。