有没有支持对象消息传递的Python包?
Is there a Python package that supports object message passing?
我有兴趣使我当前的 Python 项目符合面向对象的范式,因为它最初是由 Alan Kay 构想的——from my understanding,它是关于对象消息传递的——其他与对象本身有关。
我正在考虑的那种包中的示例代码可能如下所示:
def do_laundry(self):
send(self.car, "DRIVE_TO", (self.laundromat))
washing_machine = self.look_for(WashingMachine)
send(self.washing_machine, "LOAD")
...
我可以看到如何严格遵守这种范式可以简化对象接口,消息传递的基础知识似乎并不难实现,所以我很惊讶我找不到任何东西相关的。 (我发现的所有与消息相关的包都与电子邮件或其他 Internet 活动有关。)是否有一个包可以满足我的需求,或者我是否错误地认为这对 Python 拥有?可以想象这还没有完成并且可能有用,但我过去的经验表明这不太可能。
P.S。我知道 this question,但它有不同的重点,它已经 10 年没有活动了,link 到它所指的 Python-特定资源是坏了。
您可以使用发布子系统来完成此类工作。我是像 rxpy 这样的工具的忠实粉丝,但是 Pub-Sub 的核心概念很简单,您自己可以添加。以此为例:
class DriveTo:
def drive_to(self, location):
print(f"Driving To {location}")
class LoadWashingMachine:
def load_washing_machine(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat):
self._laundromat = laundromat
self._drive_to_events = []
self._load_washing_machine_events = []
def _drive_to(self, location):
for drive_event in self._drive_to_events:
drive_event.drive_to(location)
def _load_washing_machine(self):
for washing_machine_event in self._load_washing_machine_events:
washing_machine_event.load_washing_machine()
def do_laundry(self):
self._drive_to(self._laundromat)
self._load_washing_machine()
在这里我们看到每个组件都可以连接起来,而不需要了解它们的消息接收者。在您的应用程序的主体中,您将处理将每个对象链接到适当的事件方法。将其放在一起的示例:
drive_to = DriveTo()
load_washing_machine= LoadWashingMachine()
do_laundry = DoLaundry(laundromat="cleaners")
do_laundry.drive_to_events.append(drive_to)
do_laundry.load_washing_machine_events.append(load_washing_machine)
do_laundry.do_laundry()
更进一步,我们可以看到每个事件的逻辑都是冗余的。我们可以通过为事件创建一个通用的 class 来简化它。每种类型的消息都可以是不同的可观察实例,接收者可以指定他们订阅的事件类型。
class Observer(ABC):
@abstractmethod
def on_next(self, *args, **kwargs):
pass
class Observable:
def __init__(self):
self._observers = []
def subscribe(self, observer):
self._observers.append(observer)
def on_next(self, *args, **kwargs) -> None:
for observer in self._observers:
observer.on_next(*args, **kwargs)
重构我们的初始示例:
class DriveTo(Observer):
def on_next(self, location):
print(f"Driving To {location}")
class LoadWashingMachine(Observer):
def on_next(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat):
self._laundromat = laundromat
self.drive_observable = Observable()
self.load_observable = Observable()
def do_laundry(self):
self.drive_observable.on_next(self._laundromat)
self.load_observable.on_next()
do_laundry = DoLaundry(laundromat="cleaners")
do_laundry.drive_observable.subscribe(DriveTo())
do_laundry.load_observable.subscribe(LoadWashingMachine())
do_laundry.do_laundry()
rxpy 库提供了很多这样的实用程序,可以让您非常轻松地编写代码。它可以处理过滤流、组合它们、处理异常、取消订阅事件等事情。
另一种使对象更易于组合的选择是使用依赖注入 (DI) 框架或控制反转 (IoC) 框架,例如 pinject.
在这些系统中,我们可以将依赖项定义为普通构造函数参数,但允许 IoC 系统处理将它们连接在一起。开始让你 类 像往常一样:
class Car:
def drive_to(self, location):
print(f"Driving To {location}")
class WashingMachine:
def load(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat, car, washing_machine):
self._laundromat = laundromat
self._car = car
self._washing_machine = washing_machine
def do_laundry(self):
self._car.drive_to(self._laundromat)
self._washing_machine.load()
现在我们可以让 pinject 将所有东西挂钩在一起。对于 consts 之类的东西,您可以使用绑定规范来帮助 pinject 确定值应该是什么:
import pinject
class BindingSpec(pinject.BindingSpec):
def provide_laundromat(self):
return "cleaners"
obj_graph = pinject.new_object_graph(binding_specs=[BindingSpec()])
do_laundry = obj_graph.provide(DoLaundry)
do_laundry.do_laundry()
我有兴趣使我当前的 Python 项目符合面向对象的范式,因为它最初是由 Alan Kay 构想的——from my understanding,它是关于对象消息传递的——其他与对象本身有关。
我正在考虑的那种包中的示例代码可能如下所示:
def do_laundry(self):
send(self.car, "DRIVE_TO", (self.laundromat))
washing_machine = self.look_for(WashingMachine)
send(self.washing_machine, "LOAD")
...
我可以看到如何严格遵守这种范式可以简化对象接口,消息传递的基础知识似乎并不难实现,所以我很惊讶我找不到任何东西相关的。 (我发现的所有与消息相关的包都与电子邮件或其他 Internet 活动有关。)是否有一个包可以满足我的需求,或者我是否错误地认为这对 Python 拥有?可以想象这还没有完成并且可能有用,但我过去的经验表明这不太可能。
P.S。我知道 this question,但它有不同的重点,它已经 10 年没有活动了,link 到它所指的 Python-特定资源是坏了。
您可以使用发布子系统来完成此类工作。我是像 rxpy 这样的工具的忠实粉丝,但是 Pub-Sub 的核心概念很简单,您自己可以添加。以此为例:
class DriveTo:
def drive_to(self, location):
print(f"Driving To {location}")
class LoadWashingMachine:
def load_washing_machine(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat):
self._laundromat = laundromat
self._drive_to_events = []
self._load_washing_machine_events = []
def _drive_to(self, location):
for drive_event in self._drive_to_events:
drive_event.drive_to(location)
def _load_washing_machine(self):
for washing_machine_event in self._load_washing_machine_events:
washing_machine_event.load_washing_machine()
def do_laundry(self):
self._drive_to(self._laundromat)
self._load_washing_machine()
在这里我们看到每个组件都可以连接起来,而不需要了解它们的消息接收者。在您的应用程序的主体中,您将处理将每个对象链接到适当的事件方法。将其放在一起的示例:
drive_to = DriveTo()
load_washing_machine= LoadWashingMachine()
do_laundry = DoLaundry(laundromat="cleaners")
do_laundry.drive_to_events.append(drive_to)
do_laundry.load_washing_machine_events.append(load_washing_machine)
do_laundry.do_laundry()
更进一步,我们可以看到每个事件的逻辑都是冗余的。我们可以通过为事件创建一个通用的 class 来简化它。每种类型的消息都可以是不同的可观察实例,接收者可以指定他们订阅的事件类型。
class Observer(ABC):
@abstractmethod
def on_next(self, *args, **kwargs):
pass
class Observable:
def __init__(self):
self._observers = []
def subscribe(self, observer):
self._observers.append(observer)
def on_next(self, *args, **kwargs) -> None:
for observer in self._observers:
observer.on_next(*args, **kwargs)
重构我们的初始示例:
class DriveTo(Observer):
def on_next(self, location):
print(f"Driving To {location}")
class LoadWashingMachine(Observer):
def on_next(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat):
self._laundromat = laundromat
self.drive_observable = Observable()
self.load_observable = Observable()
def do_laundry(self):
self.drive_observable.on_next(self._laundromat)
self.load_observable.on_next()
do_laundry = DoLaundry(laundromat="cleaners")
do_laundry.drive_observable.subscribe(DriveTo())
do_laundry.load_observable.subscribe(LoadWashingMachine())
do_laundry.do_laundry()
rxpy 库提供了很多这样的实用程序,可以让您非常轻松地编写代码。它可以处理过滤流、组合它们、处理异常、取消订阅事件等事情。
另一种使对象更易于组合的选择是使用依赖注入 (DI) 框架或控制反转 (IoC) 框架,例如 pinject.
在这些系统中,我们可以将依赖项定义为普通构造函数参数,但允许 IoC 系统处理将它们连接在一起。开始让你 类 像往常一样:
class Car:
def drive_to(self, location):
print(f"Driving To {location}")
class WashingMachine:
def load(self):
print(f"Loading washing machine")
class DoLaundry:
def __init__(self, laundromat, car, washing_machine):
self._laundromat = laundromat
self._car = car
self._washing_machine = washing_machine
def do_laundry(self):
self._car.drive_to(self._laundromat)
self._washing_machine.load()
现在我们可以让 pinject 将所有东西挂钩在一起。对于 consts 之类的东西,您可以使用绑定规范来帮助 pinject 确定值应该是什么:
import pinject
class BindingSpec(pinject.BindingSpec):
def provide_laundromat(self):
return "cleaners"
obj_graph = pinject.new_object_graph(binding_specs=[BindingSpec()])
do_laundry = obj_graph.provide(DoLaundry)
do_laundry.do_laundry()