我主要将python用作数值模拟的胶合语言。
通常,我创建一些包装器类来初始化一些合理的默认参数,然后,在较大的脚本中的其他地方,我调用run()
方法,该方法可以选择覆盖某些参数并执行实际的模拟。
它可能看起来像这样:
class MyCalculationClass():
def __init__():
# set some defaults
self.A = 45454
self.B = np.zeros(16,11)
self.C = (1.0,2.5,30.0)
def runRaw():
return whatever(self.A,self.B,self.C)
def run( A=None, B=None, C=None ):
# optionally override some defaults
if A is not None:
self.A = A
if B is not None:
self.B = B
if C is not None:
self.C = C
# run the actual calculation
return self.runRaw()
mycalc1 = MyClaculationClass()
# .... Over the Hills and Far Away
mycalc1.run(B=np.zeros(11,12) )
但是我真的讨厌样板 if A is not None: self.A = A
。通常有数十个参数。
这样会更好
def run( A=self.A, B=self.B, C=self.C ):
# optionally override some defaults
self.A = A
self.B = B
self.C = C
# run the actual calculation
self.runRaw()
但是:
注意:我真的希望self.A
等保持存储为类属性,以便能够稍后在较大的脚本中恢复我在哪个计算中使用的参数
答案 0 :(得分:3)
如果您不介意丢失检查提供的一些自动魔术文档,则可以执行以下操作:
class Foo(object):
def __init__(self):
self._set(A=42, B=[], C="something")
def _set(self, **kw):
for name, val in kw.items():
if val is not None:
setattr(self, name, val)
def run(self, **kw):
self._set(**kw)
self.runRaw()
如果您想保持run()
签名不变,则有可能,但不会那么通用(因为run()
必须知道它是参数):
def run(self, A=None, B=None, C=None):
self._set(A=A, B=B, C=C)
self.runRaw()
还要注意,可以通过声明__call__
方法来使Python对象可调用:
class NotAFunc(object):
def __call__(self, arg):
print("{} called with {}".format(self, arg))
f = NotAFunc()
f(42)
答案 1 :(得分:1)
您可以使用关键字参数并通过defines.inc.php
方法更新对象字典(仅在变量不是类的属性时才有效。如果是这种情况,请使用update()
方法)。
setattr()
打印:
class MyCalculationClass():
def __init__(self):
# set some defaults
self.A = 45454
self.B = [0, 0, 0, 0, 0]
self.C = (1.0,2.5,30.0)
def runRaw(self):
print(self.A, self.B, self.C)
def run(self, **kwargs):
self.__dict__.update(kwargs)
return self.runRaw()
c = MyCalculationClass()
c.run(B=[1, 1, 1])
答案 2 :(得分:0)
这也可以通过装饰器来实现:
import functools
def set_if_none(method):
@functools.wraps(method)
def wrapper(self, **kwargs): # no *args without inspect.signature
for k, v in kwargs.items():
if v is not None and hasattr(self, k):
setattr(self, k, v)
result = method(self, **kwargs) # no *args
return result
return wrapper
注意:上面的示例仅适用于(使用和强制执行)关键字参数。要合并位置参数,您可能需要inspect.signature
。
示例:
class MyClass(object):
def __init__(self, a=1, b=2):
self.a = a
self.b = b
def __repr__(self):
return 'MyClass(%s)' % self.__dict__
@set_if_none
def meth(self, a=None, b=None):
pass
>>> mc = MyClass()
>>> mc
MyClass({'a': 1, 'b': 2})
>>> mc.meth(a=10)
>>> mc
MyClass({'a': 10, 'b': 2})
贷记this answer,以提醒您可以通过在装饰器中将self
(实例)传递到wrapper()
来修改类实例。