自定义装饰器不允许在 main Python 中调用函数

Custom decorator is not allowing function to be called in main Python

在我构建的特定 class 中,它本质上充当用户定义函数的包装器,除了实例化之外,用户只会使用我的 class 中的 2-3 个主要函数。我试图使我的 class 装饰器兼容,以便用户可以简单地构建他的函数并使用装饰器,而不是从我构建的 class 中显式调用 2-3 个函数。我现在正在尝试对此进行测试。

主要:

from class_I_built import ClassIBuilt

def main():
    testfcn()


@ClassIBuilt('1', MessageConverter, timeout=10)
def testfcn():
    count = 0
    while count < 1000:
        count = count + 1

main()

class_I_built

import socket
from apb import APB
import config
import time

MCAST_GRP = config.MCAST_GRP
MCAST_PORT = config.MCAST_PORT


class ClassIBuilt(APB):
    processvar = 0

    def __init__(self, id, message_protocol, timeout=config.TIMEOUT):

        self.sock = 1

        self.p_id = p_id
        self.timeout = timeout
        self.message_protocol = message_protocol

    def __call__(self, decorator_function=1):
        self.publish_start('starting message')
        decorator_function(*args, **kwargs)
        self.publish_end('ending message')

    def connect(self):
        ttl = 2
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)

    def publish(self, message_type='alert', message=''):


        self.connect()
        s = self.message_protocol(message)
        try:
            self.sock.sendto(s, (MCAST_GRP, MCAST_PORT))
        finally:
            self.sock.close()

    def publish_start(self, message=''):
        print 'publishing start'
        self.publish("start", message)

    def publish_end(self, message=''):
        print 'publishing end'
        self.publish('end', message)

如果我不在 main() 中调用 testfcn(),则会调用 __call__ 方法并正常发布开始和结束消息。但它不应该以这种方式工作,因为如果我在 main() 中显式调用 testfcn(),它应该只 运行 testfcn()。但是,如果我在 main() 中调用 testfcn(),如上所示,它会发送消息,但我收到 NoneType object is not callable 错误。

Output/stack 追踪:

publishing start
publishing end
Traceback (most recent call last):
  File "Main.py", line 13, in <module>
    main()
  File "Main.py", line 4, in main
    testfcn()
TypeError: 'NoneType' object is not callable

为什么会发生错误,如果在 main 中显式调用该函数,我该如何构建我的代码以便它仅 运行s?

你的装饰器行创建了你的 class:

的一个实例
@ClassIBuilt('1', MessageConverter, timeout=10)

然后使用该实例进行实际装饰;你实际上是这样做的:

decorator = ClassIBuilt('1', MessageConverter, timeout=10)
def testfcn(): # ...
testfcn = decorator(testfcn)

因为 decorator 是您的 class 的实例,所以 decorator(testfcn) 调用由 ClassIBuilt.__call__() 方法处理,而该方法 return没什么:

def __call__(self, decorator_function=1):
    self.publish_start('starting message')
    decorator_function(*args, **kwargs)
    self.publish_end('ending message')

没有 return 语句意味着 None 是 returned,因此 testfcn 设置为 None。您无法调用 None,导致出现异常。

您的 __call__ 应该 return 包装器:

def __call__(self, decorator_function=1):
    def wrapper(*args, **kwargs):
        self.publish_start('starting message')
        decorator_function(*args, **kwargs)
        self.publish_end('ending message')
    return wrapper

现在 testfcn 绑定到 wrapper() 函数,然后调用原始修饰函数。