【问题标题】:How are method default arguments overridden in python?如何在 python 中覆盖方法默认参数?
【发布时间】:2015-01-20 13:51:47
【问题描述】:

方法默认参数显然可以被覆盖:

>>> class B:
...     def meth(self, r=True): print r
>>> class D(B):
...     def meth(self, r=False): print r
... D().meth()
False
>>> B().meth()
True

这怎么可能?它被认为是糟糕的风格吗?

【问题讨论】:

  • 附录 (2014.11.23):用例是添加用于修改遗留代码中的方法行为的默认参数 - 不打算由调用者设置 - 应将其命名为 _r

标签: python python-2.7 inheritance methods default-arguments


【解决方案1】:

您可以以任意方式更改被覆盖方法的签名。 Python 不在乎:

class Base:
    def foo(self, x, y):
        pass

class Deriv(Base):
    def foo(self, blah=100):
        pass

但如果你问

它被认为是不好的风格吗?

答案是肯定的,因为它违反了重要的Liskov substitution principle

如果 Deriv 扩展 Base,您必须能够用 Deriv 替换所有出现的 Base 而不会破坏您的程序。

换句话说,派生类必须履行基类提供的所有契约。特别是,被覆盖的方法必须具有相同的签名和相似的语义。由于 Python 对此没有帮助,因此您必须在 IDE(此处为 Intellij IDEA)的帮助下手动控制:

要回答您关于覆盖默认参数的具体问题,我想答案是“视情况而定”。如果参数是一个仅在内部使用的选项,并且不影响对象的可观察行为,那么更改它并没有错:

class Buffer:
    def __init__(self, init_size=16):

class BigBuffer(Buffer):
    def __init__(self, init_size=1024):

另一方面,如果参数严重影响语义,它是合同的一部分,不应被覆盖。比如这段代码会让人迷惑

class Test:
    def test_equal(self, a, b, fail_if_equal=False):

class MyTest(Test):
    def test_equal(self, a, b, fail_if_equal=True):

【讨论】:

  • Pycharm?是的,我用这个。回复:我知道更改签名是不好的风格(如您的图片所示,Pycharm 中甚至有警告)但在这种特定情况下,我更改了默认值 - 没有警告。我认为这是合法的,因为 Derived.meth() 的行为应该有所不同 - 我只是通过更改默认值来实现这一点......
  • @Mr_and_Mrs_D:更新了答案以解决您的具体问题。
  • 谢谢 - 图中是 Intellij IDEA 还是 Pycharm?
  • @Mr_and_Mrs_D:这是想法,版本。 12(不是最新的)。
【解决方案2】:

这怎么可能?
机制是什么?

您只需覆盖派生类中的整个方法。

【讨论】:

    【解决方案3】:

    这是绝对允许的,但可能会让您的来电者感到非常困惑。他们不应该像使用B 对象一样使用D 对象吗?

    【讨论】:

    • 是的,从不传递参数;)——机制是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多