isnt this the opposite of how a decorator works?
Yesterday we upgraded our slackclient module in python and needed to change some code based on this migration guide for the RTM API.
Here is my code...
import slack slack_token = os.environ['SLACK_BOT_TOKEN'] rtmclient = slack.RTMClient(token=slack_token) @slack.RTMClient.run_on(event='message') def parse_message(**payload): data = payload['data'] channel_id = data['channel'] print(data) print(channel_id) rtmclient.start()
I had never worked with a Python decorator before this.
After reading up on decorators, it was my understanding that the decorator
slack.RTMClient.run_on would be called if I were to call the function
This code appears to be doing the opposite.
Why/how does this code work when
rtmclient.start() is called?
Not familiar with that particular API, but
@slack.RTMClient.run_on(event='message') def parse_message(**payload): ...
is essentially the same as
def parse_message(**payload): ... parse_message = slack.RTMClient.run_on(event='message')(parse_message)
The decorator is not called when the function is called, but when it is declared. It will then usually define and return a new function that will be called instead of the original function, e.g. with additional logging, memoization, and the like.
But it is also perfectly possible for a decorator to just return the original version of the function,1 but e.g. register that function as a callback for some events.
A very much simplified example:
my_callbacks =  def register(f): my_callbacks.append(f) return f @register def foo(): print("calling foo") for f in my_callbacks: f()
1) As noted in comments, this decorator seems to not even return the original function but
None, meaning that the function will no longer be directly callable after being decorated, only via the callback.