有没有办法绕过__init__
python中的类的构造函数?
例:
class A(object):
def __init__(self):
print "FAILURE"
def Print(self):
print "YEHAA"
现在,我想创建一个实例A
。看起来可能像这样,但是这种语法不正确。
a = A
a.Print()
编辑:
一个更复杂的示例:
假设我有一个对象C
,目的是存储一个参数并对其进行一些计算。但是,该参数并未按原样传递,而是被嵌入到巨大的参数文件中。它可能看起来像这样:
class C(object):
def __init__(self, ParameterFile):
self._Parameter = self._ExtractParamterFile(ParameterFile)
def _ExtractParamterFile(self, ParameterFile):
#does some complex magic to extract the right parameter
return the_extracted_parameter
现在,我想转储并加载该对象的实例C
。但是,当我加载该对象时,我只有一个变量,self._Parameter
并且无法调用构造函数,因为它需要参数文件。
@staticmethod
def Load(file):
f = open(file, "rb")
oldObject = pickle.load(f)
f.close()
#somehow create newObject without calling __init__
newObject._Parameter = oldObject._Parameter
return newObject
换句话说,在不传递参数文件的情况下无法创建实例。但是,在我的“真实”情况下,它不是参数文件,而是一些巨大的数据,我当然不希望在内存中随身携带,甚至不希望将其存储到磁盘上。
而且由于我想C
从方法中返回一个实例,所以Load
我不得不以某种方式调用构造函数。
旧编辑:
一个更复杂的示例,它解释了为什么我要问这个问题:
class B(object):
def __init__(self, name, data):
self._Name = name
#do something with data, but do NOT save data in a variable
@staticmethod
def Load(self, file, newName):
f = open(file, "rb")
s = pickle.load(f)
f.close()
newS = B(???)
newS._Name = newName
return newS
如您所见,由于data
未存储在类变量中,因此无法将其传递给__init__
。当然,我可以简单地存储它,但是如果数据是一个巨大的对象,而我又不想一直将其存储在内存中甚至将其保存到磁盘上怎么办?
您可以__init__
通过__new__
直接致电来规避。然后,您可以创建给定类型的对象,并为调用替代方法__init__
。这是pickle
可以做到的。
但是,首先,我非常想强调一点,这是您不应该做的事情,无论您要达到什么目的,都有更好的方法可以做到,其中一些已在其他答案中提到。特别是,跳过call 是一个坏主意__init__
。
创建对象时,或多或少会发生这种情况:
a = A.__new__(A, *args, **kwargs)
a.__init__(*args, **kwargs)
您可以跳过第二步。
这就是为什么您不应该这样做的原因:的目的__init__
是初始化对象,填写所有字段并确保__init__
还调用父类的方法。有了pickle
它是一个例外,因为它尝试存储与该对象关联的所有数据(包括为该对象设置的任何字段/实例变量),因此,__init__
上次设置的任何内容都将由pickle还原,没有需要再次调用它。
如果跳过__init__
并使用替代的初始化程序,则会有某种形式的代码重复-实例变量将在两个位置填充,并且很容易在其中一个初始化程序中错过其中一个,或者不小心使其中一个两个填充字段的行为不同。这样就可以发现难以跟踪的细微错误(您必须知道调用了哪个初始化程序),并且代码将更难以维护。更不用说如果您使用继承会陷入更大的混乱-问题将在继承链中蔓延,因为您必须在链的各处使用此替代初始化器。
通过这样做,您或多或少会覆盖Python的实例创建并自行创建。Python已经为您很好地做到了这一点,无需重新发明它,它会使使用您的代码的人们感到困惑。
最好的替代__init__
方法是:对于将所有实例变量正确初始化的类的所有可能实例,请使用单个方法。对于不同的初始化模式,请使用以下两种方法之一:
__init__
通过使用可选参数,为处理您的案件提供不同的签名。__init__
)创建类的实例,如Roman Bodnarchuk所示,同时执行其他工作或执行其他操作。最好将它们传递给类(并__init__
处理)所有数据,但是如果这是不可能或不方便的,则可以在创建实例并__init__
完成初始化之后设置一些实例变量。如果__init__
具有可选步骤(例如,像处理该data
参数那样,尽管您必须更具体一些),则可以将其设为可选参数,也可以将其设为执行该处理的常规方法...或同时执行两者。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句