在我构建的特定类中,它基本上充当用户定义函数的包装器,除了实例化之外,用户只会使用我的类中的2-3个主要函数。我试图使我的类装饰器兼容,以便用户可以简单地构建他的函数并使用装饰器而不是从我构建的类中显式调用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__方法,并正常发布开始和结束消息。它应该不会这样工作,因为它应该只运行testfcn()如果我在main()中显式调用testfcn()。但是,如果我在main()中调用testfcn(),如上所示,那么它将发送消息但我得到一个NoneType对象是不可调用的错误。
输出/堆栈跟踪:
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中显式调用该函数时它才会运行?
答案 0 :(得分:3)
您的装饰线创建了一个类的实例:
@ClassIBuilt('1', MessageConverter, timeout=10)
然后该实例用于进行实际装饰;你实际上是这样做的:
decorator = ClassIBuilt('1', MessageConverter, timeout=10)
def testfcn(): # ...
testfcn = decorator(testfcn)
由于decorator
是您班级的一个实例,decorator(testfcn)
调用由ClassIBuilt.__call__()
方法处理,而该方法不返回任何内容:
def __call__(self, decorator_function=1):
self.publish_start('starting message')
decorator_function(*args, **kwargs)
self.publish_end('ending message')
没有return
语句表示返回None
,因此testfcn
设置为None
。您无法致电None
,导致您看到异常。
您的__call__
应该返回一个包装器:
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()
函数,然后调用原始修饰函数。