延迟Python中对象的初始化,直到所有信息都可用

时间:2015-08-18 02:10:14

标签: python

我的项目中有一种情况,为了初始化我需要的对象,比如3个参数。但是,在施工期间,我只有2个可用的参数。然后,稍后可以使用第三个参数。 此时我希望初始化对象。

以下是我解决它的方法:

class Base(object):
    #abstract
    def initialize(self, extraArgs):        
        raise NotImplementedError()

class Derived(Base):
    def __init__(self, arg1, arg2):
        def closure(self, extraArgs): 
            self._initialize(extraArgs, arg1, arg2)
        self.initialize = types.MethodType(closure, self)

    def _initialize(self, extraArgs, arg1, arg2):
        # do something with all of extraArgs, arg1, arg2


d = Derived(x, y) #only x and y are available at this point

#in a later context working with Base class, the missing z is available
d.initialize(z)

有没有更好的方法来实现这一目标?我怎么能避免" extraArgs,arg1,arg2"的三重复制?

2 个答案:

答案 0 :(得分:0)

您可以使用functools中的partial。你可以传递类名和2个参数,然后在你正确时传递第三个并返回你需要的对象。

class P(object):
    def __init__(self, a, b, c):
        self.a=a
        self.b=b
        self.c=c

from functools import partial
pa = partial(P, 1, 2)
pa # This is a partial, not the oject you need
<functools.partial at 0x7feeb00e7e68>
pa(3) # This is the object you need
<__main__.P at 0x7feeb00d8bd0>

答案 1 :(得分:0)

实际上我认为你想要实现的目标不需要继承。您可以在Python中使用元编程,因为 Class 也是一个对象。

这里对类的属性的修改被“反映”到它已经初始化的对象。因此,您无需担心何时初始化它。

class SomeClass():
    """
    use variable arguments so it's ok to initialize
    with any number of arguments
    """
    def __init__(self, *args):
        for index, arg in enumerate(args):
            # do something with the arguments                                                                                     
            if index == 0:
                self.arg1 = arg
            elif index == 1:
                self.arg2 = arg
            elif index == 2:
                self.arg3 = arg

class Revealer():
    """
    Inject random cute words to SomeClass's third argument
    """
    def __init__(self):
        self.misty = ["baz","maple", "syrup", "baby", "cereal"]
        self.gen = self.misty_generator()

    def misty_generator(self):
        for i in self.misty:
            yield i

    def inject_misty(self, class_):
        class_.arg3 = self.gen.next()

# Meta-programming                                                                                                                
SomeClass.arg1 = "cake"
SomeClass.arg2 = "merinque"                                                                             
SomeClass.arg3 = lambda self: None

d = SomeClass("foo", "bar")
print(d.arg1, d.arg2, d.arg3())  # print "foo", "bar", None

r = Revealer()

r.inject_misty(SomeClass) 
print(d.arg1, d.arg2, d.arg3)    # print "foo", "bar", "baz"

r.inject_misty(SomeClass)
print(d.arg1, d.arg2, d.arg3)    # print "foo", "bar", "maple"

r.inject_misty(SomeClass)
print(d.arg1, d.arg2, d.arg3)    # print "foo", "bar", "syrup"