Python decorator
An adorner is essentially a Python function that allows other functions to add extra functionality without any code changes, and the return value of the adorner is also a function object. It is often used in scenarios where there is a need for facets, such as inserting logs, performance testing, transaction processing, caching, permission checking, and so on. Adorners are a great design for solving such problems, and with adorners, we can pull out a lot of similar code that is not related to the function itself and continue to reuse it.
Write a simple decorator
def deco(f): def wrapped(*args, **kwargs): print "start" f(*args, **kwargs) print "end" return wrapped@decodef func(a): print afunc("func run")
The running code eventually gets:
startfunc runend
The example code provides a better understanding of the adorner's definition.
Adorner with parameters
def deco(level): def wrapped(f): def wrapper_inner(*args, **kwargs): print "%s start" % level f(*args, **kwargs) print "end" return wrapper_inner return wrapped@deco("i am info")def func(a): print afunc("func run")
As used in the adorner definition, we may need to enter different levels when printing the log.
From here you can also see the parameters of the adorner in the order, from top to bottom, adorner parameters, adorner modifier functions, and function parameters
Built-in adorners
The built-in adorner differs from the general decorator in that it returns a class object,
@property
class TestEntiy(object): def __init__(self): super(TestEntiy, self).__init__() self._position = 5 @property def position(self): return self._position @position.setter def position(self, value): self._position = value @position.deleter def position(self): del self._position
Use @ Syntax sugar, more concise implementation of get and set
However, it is important to note that setter and deleter are the 23rd parameters of the property and cannot be used directly with the @ syntax, but should be called using an existing Peoperty object.
@staticmethod and @classmethod
Returns the Staticmethod and Classmethod objects, respectively, to invoke the decorated function, which can only be invoked using a class call rather than an object
Implement event callback semantics based on adorners
In completing the game job using unity as the client, Python does the service side. Because the scripting language used by Unity is C #, when data synchronization is complete, the delegate & event semantics are used to implement the event callback when data is being distributed for the server, which solves the tight coupling between the data management entity and the socket Network Service entity code. However, after changing the client engine and using Python to develop the client, in order to implement the event callback semantics to solve the server-side data distribution to the various data management entities, the Python language decorator syntax sugar to learn
def msg_listener(*events): def wrapper(func): func.events = events return func return wrapper
The first is the adorner, for the decorated function object plus the Events property, where Python is very nasty, everything is object
And then we're going to look at what the events in each of these functions are.
class Msgnotifierevent (object): _events = [] def __init__ (self, name): Super (Msgnot Ifierevent, self). __init__ () Self._name = name Self._callback = [] Msgnotifierevent._events.append (SE LF) def __iadd__ (self, callback): Self._callback.append (callback) return self def __call__ (self, *args , **kwargs): for CB in SELF._CALLBACK:TRY:CB (*args, **kwargs) except Excepti On as E:print "Msgnotifier callback error, Function:", cb.__name__, E @classmethod def clear (CLS, NA ME): For event in cls._events:if Event._name = = Name:event._callback = [] Break
This is written from the __call__ function, so the main use is actually called when this object, then _callback inside what is it?
Here is the base class for my client data management, which consists mainly of the logic of data snooping (event callback), where you can see that the Init_data_listener function gets all the functions that contain the events property. Add these functions to the callback queue for events (here you can look at the overloads of the code for __iadd__), so that the call to the listener Msgnotifierevent is fully implemented, and the callback of the data processing function is realized
# -*- coding: utf-8 -*-import abcimport inspectclass ManagerBase(object): #包含数据接受的实体基类,需自己实现destroy函数,清除监听器和事件 __metaclass__ = abc.ABCMeta def __init__(self): super(ManagerBase, self).__init__() self.init_data_listener() def init_data_listener(self): for listener_name, listener in inspect.getmembers(self, lambda f: hasattr(f, ‘events‘)): for event in listener.events: event += listener @abc.abstractmethod def destroy(self): raise NotImplementedError
The following is the test code
class TestEntiy(ManagerBase): def __init__(self): super(TestEntiy, self).__init__() @msg_listener(game_msg_recv) def update(self, protocol): print "this is deal data:", protocol def destroy(self): MsgNotifierEvent.clear("game_msg_recv") test = TestEntiy()game_msg_recv("i am test1")test.destroy()game_msg_recv("i am test2")#输出#this is deal data: i am test1
Python Decorator Learning