根据对象的实例化位置对对象实例化执行其他操作



我有一个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

关键是构造函数将在构造时调用。然后,诀窍是决定需要选择性地调用哪些其他东西。

最新更新