【问题标题】:Is there an alternative to using multiple inheritance in python in my case?在我的情况下,是否可以在 python 中使用多重继承?
【发布时间】:2021-01-06 21:42:39
【问题描述】:

假设有几个类

class Order:
  def create_basic_order(self):
    pass
    # something here

  def create_difficult_order(self):
    pass
    # something here  


class Point:
  def create_full_point(self):
    pass
    # something here

  def create_limited_point(self):
    pass
    # something here

并且客户端以json格式发送带有特定命令的请求。例如{"command": "create_limited_point"}

并且服务器应该执行适当的命令。在这种情况下:Point().create_limited_point()

所有命令都不同。 没有“if 构造”的最明显方法是这样的:

class App(Order, Point):
  pass
  # maybe something here

# Code to handle client request
command = 'create_limited_point'
a = App()
method_to_call = getattr(a, command)
method_to_call()

App 类收集了客户端可以使用的所有方法。 这是完成手头任务的好方法吗?

【问题讨论】:

  • 您能提供更多信息吗?当这个例子实际上什么也没做时,真的很难说什么是合适的。您可以通过继承进行组合并搜索组件。您可以进行从名称到可调用的映射,并完全跳过类结构。您可以进行类似的映射,但在所有类上使用 dir 自动创建它。您可以使用装饰器来注册每个命令。你可以...
  • @MisterMiyagi 主要问题是我需要执行客户端发送的命令。这可以通过将方法(命令)放在一个类中并按名称调用它来完成。但是这个类可以随着客户想要执行的命令的增长而增长。为此,我可以将类拆分为逻辑子类。但是如何理解我需要从哪个类调用客户端方法呢?
  • 更多信息需要给出一个好的答案,尤其是关于你的课程。它们是否仅作为命令的集合存在,或者即使没有命令,它们也会是离散的类?
  • 想法是用户给出一个命令,这个命令必须被执行。命令本身可以在逻辑上进行划分。例如,一些命令指的是一个订单,一些指的是一个点。因此,问题是如何正确分解。

标签: python inheritance design-patterns django-rest-framework multiple-inheritance


【解决方案1】:

我不确定您的应用是什么,但您是对的,您建议的解决方案很糟糕。如果可以的话,你可能应该稍微重构一下这段代码。多重继承通常是个坏主意。

类似的东西可能更适合你。

import abc
from typing import Dict


class EventHandler(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def handle(self):
        pass


class BasicOrderHandler(EventHandler):
    def handle(self):
        pass


class DifficultOrderHandler(EventHandler):
    def handle(self):
        pass


class FullPointHandler(EventHandler):
    def handle(self):
        pass


class LimitedPointHandler(EventHandler):
    def handle(self):
        pass


class App:
    commands_handlers_mapper: Dict[str, EventHandler] = {
        'create_limited_point': LimitedPointHandler,
        'create_full_point': FullPointHandler,
        'create_difficult_order': BasicOrderHandler,
        'create_basic_order': BasicOrderHandler
    }

    def execute_command(self, command: str) -> None:
        handler = self.commands_handlers_mapper[command]
        handler.handle()


command = 'create_limited_point'
a = App()
a.execute_command(command)

将这些commands 放入常量的奖励积分,这只是一个类属性、枚举或只是分配给变量的字符串。

【讨论】:

  • 中间类的目的是什么?为什么不只存储函数/可调用对象?
  • 拥有和使用界面。
  • 那个接口只是一个调用。它实际上不包含任何“可调用”尚未表达的信息。
  • 直到你需要更多的代码,是的。很明显,您可以在这个使用函数的简单示例中实现相同的目标。 OP 从一开始就想从 OOP 开始。就是这样。
  • 事实证明,对于每个命令,我都需要创建自己的类,即使可以有很多这样的命令?有趣:)
【解决方案2】:

由于App 仅用作命名空间,因此不需要多重继承的复杂性。只使用可调用的显式命名空间更容易、更灵活。

order = Order()

def hello():
    return 'Hello!'

commands = {
    # arbitrary callable
    'hello': hello,
    # methods of shared object
    'create_basic_order': order.create_basic_order,
    'create_difficult_order': order.create_difficult_order,
    # methods of individual objects
    'create_full_point': Point().create_full_point,
    'create_limited_point': Point().create_limited_point
}

# execute command by name
command = 'create_limited_point'
commands[command]()

当然,人们可以根据需要自动化这方面的各个部分。

# automatically use name of callable as command name
commands = {
    call.__name__: call
    for call in (
        hello,
        Point().create_full_point, Point().create_limited_point,
    )
}
# add all public methods of an object
for name in dir(order):
    if name.startswith('_'): continue
    commands[name] = getattr(order, name)

【讨论】:

    猜你喜欢
    • 2012-08-11
    • 1970-01-01
    • 2016-07-05
    • 2016-03-06
    • 2017-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多