@ThiefMaster のやり方に投票します。生活を複雑にしたい場合は、デコレータでメタクラスを使用できます。
from functools import wraps
class PreprocessMetaclass(type):
def __new__(cls, name, bases, dct):
try:
if Data in bases and "preprocess_data" in dct:
f = dct["preprocess_data"]
@wraps(f)
def preprocess_data(self, *args, **kwargs):
self.data = self.data.copy()
return f(self, *args, **kwargs)
attrs = dct.copy()
attrs["preprocess_data"] = preprocess_data
except NameError as e:
# This is if Data itself is being created, just leave it as it is.
# Raises an NameError, because Data does not exist yet in "if Data in bases"
attrs = dct
return super(PreprocessMetaclass, cls).__new__(cls, name, bases, attrs)
class Data(object):
# This here works if the subclasses don't specify
# their own metaclass that isn't a subclass of the above.
__metaclass__ = PreprocessMetaclass
def __init__(self, data):
self.data = data
self.valid = False
#Analyze and validate data
self.preprocess_data()
self.validate_data()
def preprocess_data(self):
self.data["newkey"] = 3
def validate_data(self):
print "This is the result: self.data =", self.data
class MyData(Data):
def __init__(self, data):
super(MyData,self).__init__(data)
def preprocess_data(self):
"""The docs of the subclass"""
self.data["newkey"] = 4
if __name__ == "__main__":
dct1, dct2 = {"data": 1}, {"mydata": 2}
print "Create Data"
d = Data(dct1)
print "Create MyData"
md = MyData(dct2)
print "The original dict of Data (changed):", dct1
print "The original dict of MyData (unchanged):", dct2
# If you do that, you will see that the docstring is still there,
# but the arguments are no longer the same.
# If that is needed (you don't have arguments, but the subclass might have)
# then just enter the same arguments as the subclass's function
# help(MyData)
PSメタクラスを使用する必要があったのはこれが初めてですが、ここでは完璧なシナリオです。クラスが作成される前 ( の前__init__
) に、関数定義をオーバーライドする必要があります。今は必要ないかもしれませんが、より一般的には、それを使わざるを得ないかもしれません。
さらに簡単な例:
if not (self.preprocess_data is Data.preprocess_data):
self.data = self.data.copy()
self.preprocess_data()