Python学习3-Delegate

"Python学习"

Posted by Mas9uerade on April 17, 2018

“Python的委托”

Python中的Delegate

首先,python是一个动态语言,附上一段Wiki上对动态语言的定义。

Dynamic programming language, in computer science, is a class of high-level programming languages which, at runtime, execute many common programming behaviors that static programming languages perform during compilation. These behaviors could include extension of the program, by adding new code, by extending objects and definitions, or by modifying the type system. Although similar behaviours can be emulated in nearly any language, with varying degrees of difficulty, complexity and performance costs, dynamic languages provide direct tools to make use of them. Many of these features were first implemented as native features in the Lisp programming language.

Most dynamic languages are also dynamically typed, but not all are. Dynamic languages are frequently (but not always) referred to as “scripting languages”, although the term “scripting language” in its narrowest sense refers to languages specific to a given run-time environment.

因此,Python的委托的实现,非常简单,在这个例子中,B的一个属性为A(),并重载了getattr(), 使得B可以通过getattr()访问A的属性,从而访问了A的函数f_one(),但也由于重载的原因,不能访问自己的函数f_three();

class A:
    def f_one(self, x):
        pass

    def f_two(self):
        pass

class B():
    def __init__(self):
        self._a = A()

    def f_three(self):
        pass

    def __getattr__(self, name):
        return getattr(self._a, name)


b = B();
print(b.__getattr__("f_one"))
#print(b.__getattr__(("f_three")))     

这个例子是展示使用getattr()直接访问属性的办法,直接让一个Class获取了wrapper的属性,去调用wrapper的函数

class Wrapper:
    def __init__(self, obj):
        self.wrapper = obj

    def __getattr__(self, item):
        print("trace:", item)
        return getattr(self.wrapper, item)


if __name__ == '__main__':
    x = Wrapper([1, 2, 3, 4])
    x.append(35)
    x.remove(2)
    print(x.wrapper)  # [1,3,4,35]
    pass

最后是C#式的Delegate的实现,全局函数,类的函数,回调都能被成功调用

#  C#式的delegate
class Foo(object):
  def __init__(self):
    self._bar_observers = []

  def add_bar_observer(self, observer):
    self._bar_observers.append(observer)

  def notify_bar(self, param):
    for observer in self._bar_observers:
      observer(param)

def observer(param):
  print ("observer(%s)" % param)

class Baz(object):
  def observer(self, param):
    print ("Baz.observer(%s)" % param)

class CallableClass(object):
  def __call__(self, param):
    print ("CallableClass.__call__(%s)" % param)

baz = Baz()

foo = Foo()
class BaseEvent(object):
    temp = 0
    def __init__(self):
        self.temp = 1

class BigEvent(BaseEvent):
    def __init__(self):
        super(BigEvent, self).__init__()
        print("BigEvent Run fast")

#super相当于C#的base

class EventCenter:
    def __init__(self):
        self. delList = dict()

    def addevent(self, eventid, eventhandle):
        if eventid in self.delList.keys():
            self.delList[eventid].append(eventhandle)
        else:
            self.delList.setdefault(eventid,[])
            self.delList[eventid].append(eventhandle)

    def sendevnet(self, eventid, param):
        if eventid in self.delList.keys():
            for evhandle in self.delList.get(eventid):
                evhandle(param)
                #self.delList[eventid](param)
                #print(self.delList[eventid](param))

    def removeevent(self,eventid, eventhandle):
        if eventid in self.delList.keys():
            dictitem = {eventid: []}
            for evhandle in self.delList.get(eventid):
                if eventhandle != evhandle:
                    dictitem[eventid].append(evhandle)
            if dictitem.values().__len__() > 0:
                self.delList.update(dictitem)

def method1(baseevent):
    print("method1", baseevent.temp)

def method2(baseevent):
    print("method2", baseevent.temp)

def method3(baseevent):
    print("method3", baseevent.temp)


aeventcenter = EventCenter()
baseev = BaseEvent()
bigev = BigEvent()
aeventcenter.addevent(1, method2)
aeventcenter.addevent(1,method1)
aeventcenter.addevent(1,method3)
aeventcenter.removeevent(1, method3)
aeventcenter.sendevnet(1,bigev)
foo.add_bar_observer(observer) # function
foo.add_bar_observer(baz.observer) # bound method
foo.add_bar_observer(CallableClass()) # callable instance

foo.notify_bar(3)

最后用Python实现一个事件中心

#事件基类
class BaseEvent(object):
    temp = 0
    def __init__(self):
        self.temp = 1

#事件子类
class BigEvent(BaseEvent):
    def __init__(self):
        super(BigEvent, self).__init__()
        print("BigEvent Run fast")

#super相当于C#的base

#事件中心
class EventCenter:
    def __init__(self):
        self. delList = dict() #使用dict持有引用

    #注册事件    
    def addevent(self, eventid, eventhandle):
        if eventid in self.delList.keys():
            self.delList[eventid].append(eventhandle)
        else:
            self.delList.setdefault(eventid,[])
            self.delList[eventid].append(eventhandle)

    #发送事件 -- python的优势在这里体现,参数的传入不需要限定类型
    def sendevnet(self, eventid, param):
        if eventid in self.delList.keys():
            for evhandle in self.delList.get(eventid):
                evhandle(param)
                #self.delList[eventid](param) 这个方式是不行的
                #print(self.delList[eventid](param))

    #删除事件 -- Python的Dict相较于C#的dict和delegate的难用也体现出来了    
    def removeevent(self,eventid, eventhandle):
        if eventid in self.delList.keys():
            dictitem = {eventid: []}
            for evhandle in self.delList.get(eventid):
                if eventhandle != evhandle:
                    dictitem[eventid].append(evhandle)
            if dictitem.values().__len__() > 0:
                self.delList.update(dictitem)

def method1(baseevent):
    print("method1", baseevent.temp)

def method2(baseevent):
    print("method2", baseevent.temp)

def method3(baseevent):
    print("method3", baseevent.temp)


aeventcenter = EventCenter()
baseev = BaseEvent()
bigev = BigEvent()
aeventcenter.addevent(1, method2)
aeventcenter.addevent(1,method1)
aeventcenter.addevent(1,method3)
aeventcenter.removeevent(1, method3)
aeventcenter.sendevnet(1,bigev)