ane*_*kix 4 python first-class-functions observer-pattern
我正想通过后交有关如何观察者模式可以在Python中实现.在同一篇文章中有这些评论.
1)在python中你也可以只使用普通函数,"观察者"类并不是真正需要的.
2)这是Java程序员在切换到Python后尝试做的很好的例子 - 他们觉得Python缺少所有垃圾并尝试"移植"它.
这些注释暗示观察者模式在python中并不真正有用,并且存在其他方法来实现相同的效果.这是真的,如果能做到这一点?
这是观察者模式的代码:
class Observable(object):
def __init__(self):
self.observers = []
def register(self, observer):
if not observer in self.observers:
self.observers.append(observer)
def unregister(self, observer):
if observer in self.observers:
self.observers.remove(observer)
def unregister_all(self):
if self.observers:
del self.observers[:]
def update_observers(self, *args, **kwargs):
for observer in self.observers:
observer.update(*args, **kwargs)
from abc import ABCMeta, abstractmethod
class Observer(object):
__metaclass__ = ABCMeta
@abstractmethod
def update(self, *args, **kwargs):
pass
class AmericanStockMarket(Observer):
def update(self, *args, **kwargs):
print("American stock market received: {0}\n{1}".format(args, kwargs))
class EuropeanStockMarket(Observer):
def update(self, *args, **kwargs):
print("European stock market received: {0}\n{1}".format(args, kwargs))
if __name__ == "__main__":
observable = Observable()
american_observer = AmericanStockMarket()
observable.register(american_observer)
european_observer = EuropeanStockMarket()
observable.register(european_observer)
observable.update_observers('Market Rally', something='Hello World')
Run Code Online (Sandbox Code Playgroud)
有许多不同的方法可以在python中"观察"某些东西.使用属性描述符,自定义__setattr__
,装饰器 ......
这是一个使用第一类函数的简单示例:
class Foo(object):
def __init__(self):
self.observers = []
def register(self, fn):
self.observers.append(fn)
return fn # <-- See comments below answer
def notify_observers(self, *args, **kwargs):
for fn in self.observers:
fn(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
然后,您可以注册任何可调用的.
class Bar(object):
def do_something(self, *args, **kwargs):
pass # do something
foo = Foo()
bar = Bar()
foo.register(bar.do_something)
Run Code Online (Sandbox Code Playgroud)
这将正常工作.呼叫do_something
将具有正确的self
值.因为对象的方法是可调用对象,它们带有对它们绑定的实例的引用.
这可能有助于理解它是如何工作的:
>>> bar
<Bar object at 0x7f3fec4a5a58>
>>> bar.do_something
<bound method Bar.do_something of <Bar object at 0x7f3fec4a5a58>>
>>> type(bar.do_something)
<class 'method'>
>>> bar.do_something.__self__
<Bar object at 0x7f3fec4a5a58>
Run Code Online (Sandbox Code Playgroud)
[编辑:装饰者例子]
您也可以使用register
我们上面定义的方法作为装饰器,如下所示:
foo = Foo()
@foo.register
def do_something(*args, **kwargs):
pass # do something
Run Code Online (Sandbox Code Playgroud)
为此,只需记住register
需要返回它注册的callable.
归档时间: |
|
查看次数: |
918 次 |
最近记录: |