我会投票支持@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()