Python 在类中设置默认值
我正在用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
类图:
定义初始(自我,**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
会让我口齿不清,因此我会给出评论而不是答案。