python - 从抽象类继承时如何避免重复参数定义?
问题描述
我有一个用 Python 编写的抽象类:
class AbsctracClass(ABC):
@abstractmethod
def method(self,
value1: int,
value2: float,
value3: str,
value4: Optional[list] = None,
value5: Optional[int] = None,
value6: Optional[float] = None,
... etc ...,
):
''' An abstract method for an abstract class '''
它有一个带有很多参数的抽象方法。我知道,我知道,将大量参数传递给函数不是一个好习惯,但现在这与我的问题无关。
现在我想编写另一个继承自 AbstractClass 的类。而且我必须手动复制所有参数及其来自抽象类的类型提示。
class AnotherClass(AbstractClass):
def method(self,
value1: int,
value2: float,
value3: str,
value4: Optional[list] = None,
value5: Optional[int] = None,
value6: Optional[float] = None,
... etc ...,
):
return value3 * (value2 + value3)
当我有几个抽象方法和几个类继承自它时,它不仅很麻烦,而且pylint
对代码重复感到尖叫。而且,老实说,我同意他的看法。
显然必须有更好的方法。是吗?
解决方案
NamedTuple
这里的一种解决方案可能是在抽象类和子类中使用单个参数。如果我们有这样的NamedTuple
定义:
from typing import NamedTuple, Optional
class ArgsTuple(NamedTuple):
value1: int
value2: float
value3: str
value4: Optional[list] = None
value5: Optional[int] = None
value6: Optional[float] = None
然后你可以像这样重构你的基类:
from abc import ABC, abstractmethod
# ArgsTuple as defined above
class AbstractClass(ABC):
@abstractmethod
def method(self, all_args: ArgsTuple):
''' An abstract method for an abstract class '''
您的具体实现还必须更改它们的签名method
,以保持基类和子类之间的签名相同。调用函数的方式也需要改变——method
现在只接受一个参数,所以你必须在将所有参数ArgsTuple
传递给method
.
在实现方面method
,您现在必须从ArgsTuple
方法中解压缩参数。这样做的一种方法是这样的,一些静态类型检查器可能会遇到这种情况(MyPy 可以推断类型,但如果我没记错的话,如果你使用元组解包,PyCharm 会丢失):
# AbstractClass as refactored above
# ArgsTuple as defined above
class AnotherClass(AbstractClass):
def method(self, all_args: ArgsTuple):
_, value2, value3, *other_args = all_args
return value3 * (value2 + value3)
另一种方法是这样的,一些静态类型检查器可能会发现它更容易处理:
# AbstractClass as refactored above
# ArgsTuple as defined above
class AnotherClass(AbstractClass):
def method(self, all_args: ArgsTuple):
value3 = all_args.value3
return value3 * (all_args.value2 + value3)
推荐阅读
- python - 使用 pandas to_sql 获取导致错误的记录行/列
- go - 如何在 Hugo 中解析变量返回的路径字符串中的括号?
- php - 如何在 PHP 中调用 AWS API 的 GetCostAndUsage
- tensorflow - 在训练期间控制 keras.layer 的权重
- sql - 在 SQL 中查找两行之间的差异并为其分配一个数值(SQLite)
- kubernetes-pod - 无法在所有 POD 中使用介质作为内存挂载指定的限制大小 emptydir 卷(tmpfs)
- php - Twilio - 发送未正确呈现的 vCard
- laravel-5 - laravel 中的路由问题如何在路由中创建许多操作?
- c# - 如何根据asp.net核心中的项目列表过滤实体
- django - django 模拟一位作者与多本书籍的关系