覆盖python中的抽象方法

pse*_*ram 7 python abstract-methods

覆盖python抽象方法时,有没有办法在方法签名中使用额外的参数覆盖该方法?

例如

抽象类=

Agent(ABC):

    @abstractmethod
    def perceive_world(self, observation):
        pass
Run Code Online (Sandbox Code Playgroud)

继承类:

Dumb_agent(Agent):

    def perceive_world(self, observation):
        print('I see %s' % observation)
Run Code Online (Sandbox Code Playgroud)

在方法签名中使用额外参数继承类:

Clever_Agent(Agent):

    def perceive_world(self, observation, prediction):
        print('I see %s' % observation)
        print('I think I am going to see %s happen next' % prediction)
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 11

您尝试做的事情会奏效——但这是一个非常糟糕的主意。

通常,您不希望在覆盖时以不兼容的方式更改方法的签名。这是Liskov 替换原则的一部分。

在 Python 中,通常有很好的理由来违反这一点——继承并不总是关于子类型。

但是当您使用 ABC 定义接口时,这明确地与子类型有关。这是ABC子类和abstractmethod装饰器的唯一目的,因此使用它们来表示其他任何东西充其量是极具误导性的。


更详细地:

通过继承 from Agent,您声明了 的任何实例Clever_Agent都可以像Agent. 这包括能够调用my_clever_agent.perceive_world(my_observation). 事实上,它不仅包括这些;这就是它的全部含义!如果该调用始终失败,则 noClever_AgentAgent,因此不应声称是。

在某些语言中,您有时需要伪造接口检查的方式,以便稍后可以将类型切换和/或“动态转换”回实际类型。但在 Python 中,这从来没有必要。没有“ Agents列表”这样的东西,只是一个任何东西的列表。(除非您使用可选的静态类型检查——但在这种情况下,如果您需要绕过静态类型检查,不要仅仅为了给自己设置障碍而声明静态类型。)


在 Python 中,您可以通过添加可选参数将方法扩展到其超类方法之外,这是完全有效的,因为它仍然与显式声明的类型兼容。例如,这将是一个完全合理的做法:

class Clever_Agent(Agent):
    def perceive_world(self, observation, prediction=None):
        print('I see %s' % observation)
        if prediction is None:
            print('I have no predictions about what will happen next')
        else:
            print('I think I am going to see %s happen next' % prediction)
Run Code Online (Sandbox Code Playgroud)

或者甚至这可能是合理的:

class Agent(ABC):
    @abstractmethod
    def perceive_world(self, observation, prediction):
        pass

class Dumb_agent(Agent):
    def perceive_world(self, observation, prediction=None):
        print('I see %s' % observation)
        if prediction is not None:
            print('I am too dumb to make a prediction, but I tried anyway')

class Clever_Agent(Agent):
    def perceive_world(self, observation, prediction):
        print('I see %s' % observation)
        print('I think I am going to see %s happen next' % prediction)
Run Code Online (Sandbox Code Playgroud)