python - 继承最佳实践 : *args, **kwargs 或显式指定参数

标签 python inheritance method-signature

我经常发现自己覆盖了父类的方法,并且永远无法决定是否应该显式列出给定的参数,或者只使用一揽子 *args, **kwargs 构造。一个版本比另一个更好吗?有最佳实践吗?我缺少什么(缺点)优点?

class Parent(object):

    def save(self, commit=True):
        # ...

class Explicit(Parent):

    def save(self, commit=True):
        super(Explicit, self).save(commit=commit)
        # more logic

class Blanket(Parent):

    def save(self, *args, **kwargs):
        super(Blanket, self).save(*args, **kwargs)
        # more logic

显式变体的感知好处

  • 更明确(Python 之禅)
  • 更容易掌握
  • 轻松访问函数参数

毯式变体的感知好处

  • 更干燥
  • 父类很容易互换
  • 在不触及其他代码的情况下传播父方法中默认值的更改

最佳答案

里氏替换原则

通常,您不希望方法签名在派生类型中有所不同。如果您想交换派生类型的使用,这可能会导致问题。这通常被称为 Liskov Substitution Principle .

显式签名的好处

同时,我认为您的所有方法都具有 *args**kwargs 的签名并不正确。显式签名:

  • 通过良好的参数名称帮助记录方法
  • 通过指定需要哪些参数以及哪些具有默认值来帮助记录方法
  • 提供隐式验证(缺少必需的参数会引发明显的异常)

可变长度参数和耦合

不要将可变长度参数误认为是良好的耦合实践。父类和派生类之间应该有一定的凝聚力,否则它们不会相互关联。相关代码产生反射(reflect)内聚程度的耦合是正常的。

使用可变长度参数的地方

使用可变长度参数不应该是您的首选。当你有充分的理由时应该使用它:

  • 定义函数包装器(即装饰器)。
  • 定义参数多态函数。
  • 当您可以采用的参数确实是完全可变的(例如,通用的 DB 连接函数)。数据库连接函数通常采用 connection string有许多不同的形式,包括单 arg 形式和多 arg 形式。不同的数据库也有不同的选项集。
  • ...

你做错了吗?

如果您发现您经常创建带有许多参数的方法或具有不同签名的派生方法,那么您在组织代码方面可能会遇到更大的问题。

关于python - 继承最佳实践 : *args, **kwargs 或显式指定参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14626279/

相关文章:

C++:在继承层次结构中的每个类中使用虚拟?

python - 从周围的边界框提取车牌平行四边形?

python - 避免在实例变量定义中执行

angular - 将变量传递给注入(inject)的服务以用作装饰器参数

java - Java 继承如何用于执行程序要求?

java - jsf 1.2 自定义函数可变参数签名

ios - Swift 函数/方法中的 "_"字符

python - pandas argsort 的有趣结果

python - Django、Google App Engine 和 Postgres 可以协同工作吗?

vb.net - 委托(delegate)和 ParamArray - 解决方法建议?