2011-03-08 24 views
3

在我的類的實例化過程中,我初始化了一些不可挑選的字段。因此,爲了能夠(正確)醃製我的課程,我希望我的init方法可以在取消調用時調用。看起來,這似乎與舊式課程一樣。不可能用kwargs打發新風格?

隨着新風格的課程,我需要使用__new____getnewargs__。這是我做的:

import cPickle 


class Blubb(object): 

    def __init__(self, value): 
    self.value = value 


class Bla(Blubb): 

    def __new__(cls, value): 
    instance = super(Bla, cls).__new__(cls) 
    instance.__init__(value) 
    return instance 

    def __getnewargs__(self): 
    return self.value, 

    def __getstate__(self): 
    return {} 

    def __setstate__(self, dct): 
    pass 

x = Bla(2) 
print x.value 
pickled = cPickle.dumps(x, 2) 
x_ = cPickle.loads(pickled) 
assert x_.value == 2 

這將是罰款,如果不是事實,obj = C.__new__(C, *args)。現在有**kwargs。所以我限制在我的__new____init__方法中的非關鍵字參數。

有誰知道一種方法來解決這個問題?這真的很不方便。

回答

7

鹹菜協議2想要默認呼叫cls.__new__(cls, *args),但有一種解決方法。如果您使用__reduce__,則可以返回一個將您的參數映射到__new__的函數。我能夠修改您的示例以獲得**kwargs的工作:

import cPickle 

class Blubb(object): 

    def __init__(self, value, foo=None, bar=None): 
     self.value = value 
     self.foo = foo 
     self.bar = bar 

def _new_Bla(cls, value, kw): 
    "A function to map kwargs into cls.__new__" 
    return cls.__new__(cls, value, **kw) 

class Bla(Blubb): 

    def __new__(cls, value, **kw): 
     instance = super(Bla, cls).__new__(cls) 
     instance.__init__(value, **kw) 
     return instance 

    def __reduce__(self): 
     kwargs = {'foo': self.foo, 'bar': self.bar} 
     return _new_Bla, (self.__class__, self.value, kwargs), None 

x = Bla(2, bar=[1, 2, 3]) 
pickled = cPickle.dumps(x, 2) 
y = cPickle.loads(pickled) 
assert y.value == 2 
assert y.bar == [1, 2, 3]