自定义装饰器不允许在 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()
函数,然后调用原始修饰函数。
在我构建的特定 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()
函数,然后调用原始修饰函数。