我有一个API类(它将被其他类扩展和使用):
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
@classmethod
def create(cls, **kwargs):
return cls(**kwargs)
它由以下人员扩展:
class B(A):
pass
现在,这就是我想要的:如果我像B(arg1=1, arg2=2)
一样实例化类 B,我想在初始化它时执行一些额外的操作,例如验证kwargs
参数(并且此代码应驻留在类 A 中,而不是 B 中)。然后,如果我B.create(arg1=1, arg2=2)
,则不应进行验证。
简而言之,当仅从定义的类外部初始化对象时,我想执行额外的操作;从类内的类方法启动对象不应触发任何额外的操作。
您可以使用其他参数来区分类初始化的方法:
class A(object):
def __init__(self, __a_validate=True, **kwargs):
self.kwargs = kwargs
if __a_validate:
print 'do validation'
@classmethod
def create(cls, **kwargs):
return cls(__a_validate=False, **kwargs)
演示:
>>> B.create(arg1=1, arg2=2)
<__main__.B object at 0x9b82f4c>
>>> B(arg1=1, arg2=2)
do validation
<__main__.B object at 0x9b7bbcc>
更新评论:
这是另一种解决方案。您可以在create
方法中修改类属性,例如validate
函数设置为None
,调用构造函数,然后将validate
设置回原始状态:
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
if self.validate:
self.validate(kwargs)
def validate(self, kwargs):
print 'do validation'
@classmethod
def create(cls, **kwargs):
tmp = cls.validate
cls.validate = None
instance = cls(**kwargs)
cls.validate = tmp
return instance
如果你的"额外操作"在构造函数中,那么恐怕它们总是会运行,无论你是直接实例化还是通过工厂实例化。您可以考虑仅允许通过一组工厂方法(一些带有验证,一些没有)创建对象。
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
#no extra stuff
@classmethod
def create_with_extra_stuff(cls, **kwargs):
c = cls(**kwargs)
c.extra_stuff()
return c
@classmethod
def create_withuot_extra_stuff(cls, **kwargs):
return cls(**kwargs)
@classmethod
def create(cls, with_extra_stuff = False, **kwargs):
if with_extra_stuff:
return cls.create_with_extra_stuff(**kwargs)
else:
return cls.create_without_extra_stuff(**kwargs)
当然,我不知道你的完整用例,但工厂模式几乎是为这种事情设计的。
此部分是在提出评论后添加的:
class A(object):
def __init__(self, do_extra_stuff = True, **kwargs):
if do_extra_stuff:
self.do_extra_stuff(**kwargs)
self.kwargs = kwargs
@classmethod
def create(cls, **kwargs):
return cls(do_extra_stuff = False, **kwargs)
显示替代方案的进一步编辑:
class A(object):
def __init__(self, **kwargs):
#lightweight constructor
self.kwargs = kwargs
def validate(self):
#Does not alter class variables. That would be bad in this case
#Do stuff with self.kwargs
@classmethod
def create(cls, **kwargs):
return cls(**kwargs)
main():
a = A({...})
a.validate()
b = A.create({...})
#b.validate() not called
关键是构造函数将在构造时调用。然后,诀窍是决定需要选择性地调用哪些其他东西。