over 3 years ago

Use @classmethod Polymorphism to Construct Objects Generically

看起來這個條款講得是使用 @classmethod 達到 "constructor overloading" 的效果。

下面的函式 generate_inputs() 不夠一般化,因為只能使用 PathInputData ,如果想使用其它 InputData 的子類,必須改寫程式。

class InputData(object):
    def read(self):
        raise NotImplementedError

class PathInputData(InputData):
    def __init__(self, path):
        super().__init__()
        self.path = path

    def read(self):
        return open(self.path).read()

def generate_inputs(data_dir):
    for name in os.listdir(data_dir):
        yield PathInputData(os.path.join(data_dir, name))

問題在於建立 InputData 子類的物件不夠一般化,偏偏 Python 沒有 overloading 這種東西,沒辦法另外寫個 __init__() 來處理。幸好有 @classmethod ,可以達到一樣的效果。

class GenericInputData(object):
    def read(self):
        raise NotImplementedError

    @classmethod
    def generate_inputs(cls, config):
        raise NotImplementedError

class PathInputData(GenericInputData):
    def __init__(self, path):
        super().__init__()
        self.path = path

    def read(self):
        return open(self.path).read()

    @classmethod
    def generate_inputs(cls, config):
        data_dir = config['data_dir']
        for name in os.listdir(data_dir):
            yield cls(os.path.join(data_dir, name))
← Effective Python 心得筆記: Item 23 Effective Python 心得筆記: Item 25 →
 
comments powered by Disqus