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 原则不适用,就像可以用不同的签名覆盖__init__()
方法一样。但是,PyCharm警告让我考虑是否有我可能错过的东西。我不确定我是否以敏感的方式使用@classmethod
。
我的主要问题是:PyCharm 在这里的警告是否过于热心,或者有什么理由应该避免上述模式?
此外,非常欢迎对我可能有的任何其他设计问题/误解提供任何反馈。
我会改进你的类方法。这里实际上提供了两个类方法:一个从数据文件创建类的实例,另一个从目录中的文件生成实例列表(使用第一个类方法)。此外,类方法不应该关心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
;对于它收到的用于__init__
的参数,它已经是不可知的。