Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有不同签名的Python类方法构造函数继承_Python_Python 3.x_Inheritance_Pycharm_Class Method - Fatal编程技术网

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

具有不同签名的Python类方法构造函数继承,python,python-3.x,inheritance,pycharm,class-method,Python,Python 3.x,Inheritance,Pycharm,Class Method,TLDR 我正在使用一个@classmethod作为我的类的构造函数,我需要为一个需要额外参数的特定子类使用不同的签名来重写它。PyCharm给出了一个关于重写具有不同签名的方法的警告。我想知道它是否也适用于@classmethod构造函数 我正在为我的python项目使用IDE PyCharm,我收到了以下关于重写类中方法的警告: 方法[…]的签名与类[…]中基方法的签名不匹配 我理解这与Liskov替换原则有关,这意味着父类的对象应该总是被子类的对象替换 然而,在我的例子中,我将按照某种工

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


我正在为我的python项目使用IDE PyCharm,我收到了以下关于重写类中方法的警告:

方法[…]的签名与类[…]中基方法的签名不匹配

我理解这与Liskov替换原则有关,这意味着父类的对象应该总是被子类的对象替换

然而,在我的例子中,我将按照某种工厂模式重写用作构造函数的
@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]
在这个例子中,基本上我有一个父类
parent
,它有一些所有子类都将继承的公共属性,还有一些特定的子类
ChildA
,它有一个额外的子类特定属性

因为我使用
@classmethod
作为构造函数,所以我假设Liskov原理不适用,就像
\uuuuu init\uuuu()
方法可以用不同的签名重写一样。然而,PyTalk警告让我考虑是否有什么东西我可能错过了。我不确定我是否以敏感的方式使用了
@classmethod

那么,我的主要问题是:PyCharm在这里的警告是否过于热情,或者是否有任何理由避免上述模式


此外,对于我可能遇到的任何其他设计问题/误解,欢迎提供任何反馈。

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


请注意,您不再需要从_目录重写父目录;它已经不知道它接收到哪些参数是用于
\uuuu init\uuuu

的,因为可以对实例调用classmethod,它会影响实例的可观察行为。LSP是关于实例的行为,因此它也适用于classmethod。@MisterMiyagi Fair point,从实例而不是类调用构造函数方法是否有合理的用例?@user3407000我想不出任何用例,但这与问题无关。classmethod可以从实例调用,无论是否合理。可以定义一个classbutnotinstancemethod来强制执行这些事情,但是当前的类型检查程序很可能不会得到它。老实说,我不会担心的,这些边缘案例是系统类型的人工制品,在实践中并不重要。@bad_coder实际上我认为是的,我在谷歌搜索时不知怎么错过了这一点。。。谢谢谢谢我喜欢这个解决方案。是否有任何方法可以使用类型提示来建议用户在父类和子类的情况下分别使用哪些参数?不太可能;
cls
所期望的参数集必须是动态的,而不是静态的信息,因为
cls
本身的值不是静态的。嗯,我可以看出,使用您的方法它确实必须是动态的,但是通过重写子类中与标准行为不同的构造函数方法,我认为它可以静态定义,我认为这会增加代码的清晰度。我想这是一种折衷,我最初的问题是关于为什么应该避免这种覆盖(可能的缺点)。如果你包括这些原因或赞成/反对的比较,我会将此标记为接受答案,尽管根据对我问题的评论,我认为它可能是重复的。。。
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