【问题标题】:isnt this the opposite of how a decorator works?这不是与装饰器的工作方式相反吗?
【发布时间】:2019-11-27 14:39:40
【问题描述】:

昨天我们在 python 中升级了我们的 slackclient 模块,需要根据这个 RTM API 迁移指南更改一些代码。

https://github.com/slackapi/python-slackclient/wiki/Migrating-to-2.x

这是我的代码...

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()

在此之前我从未使用过 Python 装饰器。

在阅读了装饰器之后,我的理解是,如果我要调用函数 parse_message,就会调用装饰器 slack.RTMClient.run_on

这段代码似乎在做相反的事情。

rtmclient.start() 被调用时,这段代码为什么/如何工作?

【问题讨论】:

  • 装饰器被调用而不是你的函数,真的,但是装饰器然后处理调用你的函数。根据装饰器的编码方式,它可能会调用您的函数然后执行自己的逻辑,或者它可能会执行自己的逻辑然后调用您的函数(或两者兼而有之)。装饰器是包装器。它将代码包装在您的函数周围,因此它可以执行超出您的函数实际编程执行的其他逻辑。
  • 装饰器在你定义你的函数时被调用。它只是定义parse_message 后跟parse_message = slack.RTMClient.run_on(event='message')(parse_message) 的语法糖。也许装饰器实际上并没有返回一个函数(无论是原始的还是新的)来绑定到parse_message,但是如果没有意图明确地调用该函数,那几乎没有关系。在这里,装饰器似乎用于注册回调。
  • @error 这读起来像是 cmets 中的答案。请将其发布为答案。
  • 是的,评论在我写的时候有点扩展。不过,@tobias_k 的回答涵盖了所有重要的内容。
  • 我们能不能别再说句法糖了。没有任何意义。

标签: python python-3.x slack-api python-decorators


【解决方案1】:

不熟悉那个特定的 API,但是

@slack.RTMClient.run_on(event='message')
def parse_message(**payload):
    ...

本质上与

相同
def parse_message(**payload):
    ...

parse_message = slack.RTMClient.run_on(event='message')(parse_message)

装饰器不是在函数调用时调用,而是在声明时调用。然后它通常会定义并返回一个将被调用的新函数,而不是原始函数,例如带有额外的日志记录、记忆等。

但装饰器也完全有可能只返回函数的原始版本,1 但是例如将该函数注册为某些事件的回调。

一个非常简化的例子:

my_callbacks = []
def register(f):
    my_callbacks.append(f)
    return f

@register
def foo():
    print("calling foo")


for f in my_callbacks:
    f()

1) 正如 cmets 中所指出的,this decorator 似乎甚至不返回原始函数而是返回 None,这意味着该函数在被修饰后将不再可以直接调用,只能通过回调。

【讨论】:

  • @chepner 很有趣。使用decorator 返回None,这意味着该函数在被修饰后将是None,然后不再可用作常规函数,而只能通过回调使用。
猜你喜欢
  • 2011-07-25
  • 2019-02-23
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-24
  • 2011-02-17
  • 2011-09-30
  • 1970-01-01
相关资源
最近更新 更多