繁体   English   中英

Python 类方法构造函数 inheritance 具有不同的签名

[英]Python classmethod constructor inheritance with different signature

TLDR; 我正在使用@classmethod作为我的 class 的构造函数,并且我需要为需要额外参数的特定子 class 使用不同的签名覆盖它。 PyCharm 给出了关于覆盖具有不同签名的方法的警告。 我想知道它是否也适用于@classmethod构造函数。


我正在为我的 python 项目使用 IDE PyCharm 并且我收到以下关于覆盖 ZABB14DC2A2 中的方法的警告:

方法的签名 [...] 与 class [...] 中的基本方法的签名不匹配

我知道这与 Liskov 替换原则有关,这意味着父 class 的对象应该始终可以被子 class 的对象替换。

但是,在我的情况下,我正在重写用作构造函数的@classmethod ,遵循某种工厂模式。 我的代码的简化如下:

class Parent:
    def __init__(self, common, data):
        self.common = common
        self.data = data
    @classmethod
    def from_directory(cls, data_dir, common):
        all_data = [load_data(data_file) for data_file in get_data_files(data_dir)]
        return [cls(common, data) for data in all_data]

class ChildA(Parent):
    def __init__(self, common, data, specific):
        super().__init__(common, data)
        self.specific = specific
    @classmethod
    def from_directory(cls, data_dir, common, specific):
        all_data = [load_data(data_file) for data_file in get_data_files(data_dir)]
        return [cls(common, data, specific) for data in all_data]

在这个例子中,基本上我有一个父 class Parent ,它有一些所有子类都将继承的公共属性,还有一些特定的子 class ChildA ,它有一个额外的子类特定属性。

由于我使用@classmethod作为构造函数,我假设 Liskov 原则不适用,就像可以用不同的签名覆盖__init__()方法一样。 然而,PyCharm 警告让我考虑是否有我可能遗漏的东西。 我不确定我是否以敏感的方式使用@classmethod

那么我的主要问题是: PyCharm 是否过于热衷于此处的警告,或者是否有任何理由应该避免上述模式?

此外,任何关于我可能有的任何其他设计问题/误解的反馈都是非常受欢迎的。

我会改进你的 class 方法。 这里实际上提供了两种class 方法:一种从数据文件创建 class 的实例,另一种从目录中的文件生成实例列表(使用第一个 class 方法)。 此外, class 方法不应该关心哪个 arguments cls需要:它只是传递它接收到的任何内容(除了data ,它知道并将提供或覆盖它从文件中读取的任何内容)。

class Parent:
    def __init__(self, common, data, **kwargs):
        super().__init__(**kwargs)
        self.common = common
        self.data = data

    @classmethod
    def from_file(cls, filename, **kwargs):
        # If the caller provided a data argument,
        # ignore it and use the data from the file instead.
        kwargs['data'] = load_data(filename)
        return cls(**kwargs)

    @classmethod
    def from_directory(cls, data_dir, **kwargs):
        return [cls.from_file(data_file, **kwargs)
                for data_file in get_data_files(data_dir)]
        

class ChildA(Parent):
    def __init__(self, specific, **kwargs):
        super().__init__(**kwargs)
        self.specific = specific

请注意,您不再需要覆盖Parent.from_directory 它已经不知道它收到的 arguments 是用于__init__的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM