언어 정리/python 개념이해,문법정리

callback 함수 등록방법 4가지( 등록 VS 등록2 VS 동적등록 VS 상속)

알 수 없는 사용자 2022. 9. 5. 11:33

팁 >

1. 콜백에 parameter 값은 "맨처음 호출해주는 인자값 == 등록된 콜백함수의 parameter 값" 이랑 대응 된다.

2. 같은 id의 AgentClass 와 ClientClass 로 가장상단의 Agent의 콜백 함수 주소를 가장 하단의 Client 콜백함수 주소에 대입 한다고 보면 됨. C++ 로는 포인터주소를 변수에 저장하고 넘겨서 주소를 바꿔주는 구조

 

 


개요 :

예제 1. ( callback 등록해주는 함수 이용 )

짧게 말하면 Agnet 클래스에서 Client 클래스의 콜백 함수를 등록해 사용하는 구성이고

길게 말하면

원래는 Client 클래스의 "trigger_start()" 함수가 실행되면 3초후에 "original_callback()" 함수가 실행 되는 구조인데

Client 클래스의 "original_callback()" 함수 대신 Agent 클래스의 "transfer_callback()" 함수가 'ON'호출 되게끔 만듬

 

예제 2. ( callback 함수를 1:1 대응시켜서 바로 대입 )

client 함수에 직접 접근해서 대입  ( 이게 젤 나아보임 파이써닉한거 가틈 ㅎ)

 

예제 3. ( 상속관계로 구현 )

Agent 클래스가 Client의 callback 함수를 사용하기 위해서 callback 등록을 하는 방법 대신,

상속으로 받음으로써 callback 함수를 가져오는 구조이다.

 

--

client에 콜백함수 선언을 하지 않고 하는 방법 찾는중


등록

1. 예제 코드 :   함수정의해서 이용

import time


class ClientClass:
    def __init__(self):
        pass

    def callback_trigger_function(self, call_callback, got_data_from_somewhere):
        """ 3초후 트리거 on """
        time.sleep(3)
        call_callback(got_data_from_somewhere)

    """ original_callback 파라미터는 뭐가 오든 상관 없다. 왜냐면 주소로 매핑되는 거니까
    하지만 original_callback을 불러주는 함수에서 주는 인자값과 callback이 등록된 파라미터를 맞춰줘야함
    +>  original_callback 의 주소에 transfer_callback 의 주소가 덮어씌워지므로 original_callback 자체는 실행안됨 
        original_callback 3 개중 암거나 써도 결과는 똑같다.
    """

    # def original_callback(self,a,b,c,d,e,f,g,h,i,j,k):
    # def original_callback(self):
    #     pass
    def original_callback(self, msg):
        print('original_callback got : ', msg)

    def trigger_start(self):
        got_data_from_somewhere = 1111111
        self.callback_trigger_function(self.original_callback, got_data_from_somewhere)

    def bypass_callback_to_callback(self, event, handler):
        if event == 'transfer_now':
            self.original_callback = handler


class AgentClass:
    def __init__(self):
        self.client_class = ClientClass()
        self.setup()

    def transfer_callback(self, msg):
        print('transfer_callback got : ', msg)

    def setup(self):
        self.client_class.bypass_callback_to_callback('transfer_now', self.transfer_callback)

    def client_start(self):
        self.client_class.trigger_start()


agent_class = AgentClass()
# -> 아무일도 안일어나다가 ClientClass에 original_callback 이 실행 될 때 transfer_callback도 실행된다. parameter영역도 공유함
time.sleep(1)
agent_class.client_start()

 

 

2. 예제 코드 스크린샷 :

 


등록2

1. 예제코드 :   함수 정의 없이 ClientClass 에 직접 대입

import time

class ClientClass:
    def __init__(self):
        callback_list = []

    def client_callback(self, msg):
        print('client_callback msg : ', msg)

    def trigger_start(self):
        """ 3초후 트리거 on """
        got_data_from_somewhere = 1111111
        time.sleep(3)
        self.client_callback(got_data_from_somewhere)


class AgentClass:
    def __init__(self):
        self.client_class = ClientClass()
        self.setup()

    def setup(self):
        self.client_class.client_callback = self.agent_callback

    def agent_callback(self, msg):
        print('agent_callback msg : ', msg)

    def client_start(self):
        self.client_class.trigger_start()


agent_class = AgentClass()
agent_class.client_start()

 

2. 예제 코드 스크린샷


동적등록

1. 예제코드 :    AgentClass 에서 ClientClass 멤버변수 dictionary를 이용해서 등적등록

import time

class ClientClass:
    def __init__(self):
        self.callback_dict = {}

    # def client_callback(self, msg):
    #     print('client_callback msg : ', msg)

    def trigger_start(self, topic):
        """ 3초후 트리거 on """
        got_data_from_somewhere = '1111111'
        time.sleep(3)
        self.callback_dict[topic](got_data_from_somewhere)
        # print(self.callback_dict[topic]) #<bound method AgentClass.agent_callback of <__main__.AgentClass object at 0x7f2fdf892be0>>
        # print(type(self.callback_dict[topic])) #<class 'method'>


class AgentClass:
    def __init__(self):
        self.client_class = ClientClass()
        self.topic = None
        # self.setup()

    def setup(self, topic):
        self.topic = topic
        self.client_class.callback_dict[self.topic] = self.agent_callback

    def agent_callback(self, msg):
        print('agent_callback msg : ', msg)

    def client_start(self):
        self.client_class.trigger_start(self.topic)


agent_class = AgentClass()
agent_class.setup('/topic/_1')
agent_class.client_start()

 

 

2. 예제코드 스크린샷 :

 


상속 

1. 예제 코드 : 

import time


class ClientClass:
    def __init__(self):
        pass

    def callback_trigger_function(self, call_callback, got_data_from_somewhere):
        """ 3초후 트리거 on """
        time.sleep(3)
        call_callback(got_data_from_somewhere)

    def original_callback(self, msg):
        print('original_callback got : ', msg)

    def trigger_start(self):
        got_data_from_somewhere = 1111111
        self.callback_trigger_function(self.original_callback, got_data_from_somewhere)


class AgentClass(ClientClass):
    def __init__(self):
        super(AgentClass, self).__init__()

    def child_class_start(self):
        """ 부모클래스의 'trigger_start()' 함수를 실행 """
        self.trigger_start()


agent_class = AgentClass()
agent_class.child_class_start()

time.sleep(1)

 

2. 예제 코드 스크린샷 :

 

 


bound_method 

 

 

 

 

 

 

 


콘솔결과는 상속이나 import 해서 콜백등록이나 동일