就我而言,在 python 中是否有使用多重继承的替代方法?
Is there an alternative to using multiple inheritance in python in my case?
假设有几个 classes
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()
class应用程序收集了客户端可以使用的所有方法。
这是完成手头任务的好方法吗?
我不确定你的应用是什么,但你是对的,你建议的解决方案很糟糕。如果可以的话,您应该稍微重构一下这段代码。多重继承通常不是一个好主意。
类似的东西可能更适合你。
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
放入常量的奖励积分,这只是一个 class 属性、枚举或只是分配给变量的字符串。
由于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)
假设有几个 classes
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()
class应用程序收集了客户端可以使用的所有方法。 这是完成手头任务的好方法吗?
我不确定你的应用是什么,但你是对的,你建议的解决方案很糟糕。如果可以的话,您应该稍微重构一下这段代码。多重继承通常不是一个好主意。
类似的东西可能更适合你。
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
放入常量的奖励积分,这只是一个 class 属性、枚举或只是分配给变量的字符串。
由于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)