Есть много скрытых ловушек, которые делают этот рискованный дизайн, однако, это отличный пример обучения.
Во-первых, вызов 'self' при декорировании не удался, потому что в этой области нет self,Он существует только внутри методов.Теперь, когда простой способ уже не существует ...
myfunc является атрибутом класса App.Когда вы создаете экземпляр App, всегда вызывается одна функция.Даже когда он становится методизированным, это происходит только один раз.
a1 = App()
a2 = App()
assert a1.myfunc.__func__ is a2.myfunc.__func__
assert id(a1.myfunc) is id(a2.myfunc) # Methods have some weirdness that means that won't equate but id's show they are the same
Вот почему self необходимо для получения уникального пространства имен для экземпляра.Именно поэтому вы не сможете получить декоратор, который является уникальным для экземпляра таким образом.Еще один способ подумать о том, что класс должен быть определен до того, как вы сможете создавать экземпляры.Следовательно, вы не можете использовать экземпляр в определении класса.
Решение
Декоратор должен быть написан так, чтобы не хранить никаких атрибутов экземпляра.Вместо этого он получит доступ к атрибутам экземпляра приложения.
class MySerial():
def __init__(self):
pass # Possibly don't need to have an __init__
def write(self, serial_config):
pass # write to buffer
def read(self, serial_config):
pass # read to buffer
def decorator(self, func):
def func_wrap(self_app: App, *args, **kwargs):
self.write(func(self_app, *args, **kwars), self_app.serial_config)
return self.read(self_app.serial_config)
return func_wrap
ser = MySerial()
class App():
def __init__(self, serial_config):
self.serial_config = serial_config # This is the instance data for MySerial
@ser.decorator
def myfunc(self):
# 'yummy_bytes' is written to the serial buffer via
# MySerial's decorator method
return 'yummy_bytes'
if __name__ == '__main__':
app = App()
Теперь я предполагаю, что у MySerial будет уникальный файл, или порт, или что-то еще для каждого экземпляра приложения.Это то, что будет записано в serial_config.Это может быть не элегантно, если поток открывает закрытие, но вы сможете улучшить его для своего конкретного приложения.