我试图创建一个类(MySerial
),它实例化一个串行对象,这样我就可以对串行设备(UART)进行写/读。有一个实例方法是一个decorator,它包装了一个属于完全不同类(App
)的函数。所以decorator负责对串行缓冲区的写入和读取。在
如果我在App
类中创建MySerial
的实例,则不能使用从MySerial
创建的decorator实例方法。
{{1}因此,我尝试使用^ cd1>方法创建一个实例。在
如何做到这一点?不可能吗?在
class MySerial():
def __init__(self):
pass # I have to have an __init__
def write(self):
pass # write to buffer
def read(self):
pass # read to buffer
def decorator(self, func):
def func_wrap(*args, **kwargs):
self.write(func(*args, **kwars))
return self.read()
return func_wrap
class App():
def __init__(self):
self.ser = MySerial()
@self.ser.decorator # <-- does not work here.
def myfunc(self):
# 'yummy_bytes' is written to the serial buffer via
# MySerial's decorator method
return 'yummy_bytes'
if __name__ == '__main__':
app = App()
有很多隐藏的陷阱使得这是一个危险的设计,然而这是一个很好的学习例子。在
首先,在装饰时调用“self”失败,因为在该范围内没有self。它只存在于方法内部。既然最简单的那个已经不碍事了。。。在
myfunc是App类的属性。当你创建一个App实例时,总是调用一个函数。只有当这种情况发生的时候,才是有条理的。在
这就是为什么需要self为实例获取唯一的命名空间。这也是为什么您不能以这种方式获得实例所特有的decorator。 另一种考虑方法是,在生成实例之前必须定义类。因此,在类的定义中不能使用实例。在
解决方案
decorator需要以一种不存储任何实例属性的方式编写。它将访问应用程序实例属性。在
^{pr2}$现在我假设MySerial将为每个App实例提供一个唯一的文件、端口或其他东西。这是串行配置中记录的内容。如果流是打开一个关闭的流,这可能不太优雅,但是您应该能够为您的确切应用程序改进这一点。在
这不起作用的原因是因为您引用的是类主体中的
self
,在这里没有定义它。这里有两个解决方案。在将串行对象存储为类属性
如果您将
MySerial
实例存储为类属性,则可以在类主体中访问它:在每个实例上装饰
或者,如果每个
^{pr2}$App
实例都需要一个不同的MySerial
实例,那么您需要等待创建实例来定义一个实例属性my_func
。这意味着在每次创建实例时都会动态地修饰函数,在这种情况下,@
修饰符语法必须由函数调用替换。在此解决方案可概括为装饰多个方法或有条件地取消序列化,例如在测试环境中。在
您可以使用}。另外,请注意,在声明中,},否则将引发{}:
staticmethod
来包装decorator
。decorator
的内部func_wrap
函数在其签名中包含一个附加参数:cls
。cls
可用于访问App
实例的ser
属性,然后可以从cls.ser
调用所需的方法write
和{MySerial.write
不接受参数,而是传递包装函数的结果。下面的代码使用*args
来防止{相关问题 更多 >
编程相关推荐