正确调用装饰函数
Calling a decorated function correctly
我正在尝试从另一个 class 中重复调用装饰函数,这样每次调用函数时都会执行装饰器。
原始问题在下面,但没有正确指出与 pyqt 明确相关。
我正在尝试在 pyqt 线程中使用装饰器。根据我对装饰器的理解,每次调用函数时都应该执行装饰。 (或者至少这是我想要的。)但是,从 pyqt 线程中调用装饰函数只会导致装饰器执行一次。
这是我测试过的例子:
import time, sys
import numpy as np
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Decor:
def deco(self, *args, **kwargs):
print(kwargs['txt'])
print("In decorator")
def inner(func):
return func
return inner
dec = Decor()
class Window(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.thread = Worker()
label = QLabel(self.tr("random number"))
self.thread.output[str].connect(label.setText)
layout = QGridLayout()
layout.addWidget(label, 0, 0)
self.setLayout(layout)
self.thread.start()
class Worker(QThread):
output = pyqtSignal(str)
def run(self):
# Note: This is never called directly. It is called by Qt once the
# thread environment has been set up.
while True:
time.sleep(1)
number = self.random()
self.output.emit('random number {}'.format(number))
@dec.deco(txt='kw_argument')
def random(self):
return np.random.rand(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
我希望在调用 self.normal()
时尽可能频繁地获取 'kw_argument' 和 'in decorator' 的打印,但只获取了一次。我做错了什么?
您可以改用函数装饰器:
import time, sys
from functools import wraps
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
def dec2(*args, **kwargs):
def real_decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
print(args, kwargs)
print("In decorator")
return fn(*args, **kwargs)
return wrapper
return real_decorator
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.thread = Worker()
label = QLabel(self.tr("random number"))
self.thread.output[str].connect(label.setText)
layout = QGridLayout()
layout.addWidget(label, 0, 0)
self.setLayout(layout)
self.thread.start()
class Worker(QThread):
output = pyqtSignal(str)
def run(self):
# Note: This is never called directly. It is called by Qt once the
# thread environment has been set up.
while True:
time.sleep(1)
number = self.random()
self.output.emit('random number {}'.format(number))
@dec2(txt='kw_argument')
def random(self):
return np.random.rand(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
输出:
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
...
如果您真的需要始终打印 txt,请坚持使用 class 装饰器:
class dec2(object):
def __init__(self, *args, **kwargs):
self.deco_args = args
self.deco_kwargs = kwargs
def __call__(self, f):
def wrapped_f(*args):
print(self.deco_kwargs['txt'])
print('in decorator')
return f(*args)
return wrapped_f
输出:
w_argument
in decorator
kw_argument
in decorator
...
我正在尝试从另一个 class 中重复调用装饰函数,这样每次调用函数时都会执行装饰器。
原始问题在下面,但没有正确指出与 pyqt 明确相关。
我正在尝试在 pyqt 线程中使用装饰器。根据我对装饰器的理解,每次调用函数时都应该执行装饰。 (或者至少这是我想要的。)但是,从 pyqt 线程中调用装饰函数只会导致装饰器执行一次。
这是我测试过的例子:
import time, sys
import numpy as np
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Decor:
def deco(self, *args, **kwargs):
print(kwargs['txt'])
print("In decorator")
def inner(func):
return func
return inner
dec = Decor()
class Window(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.thread = Worker()
label = QLabel(self.tr("random number"))
self.thread.output[str].connect(label.setText)
layout = QGridLayout()
layout.addWidget(label, 0, 0)
self.setLayout(layout)
self.thread.start()
class Worker(QThread):
output = pyqtSignal(str)
def run(self):
# Note: This is never called directly. It is called by Qt once the
# thread environment has been set up.
while True:
time.sleep(1)
number = self.random()
self.output.emit('random number {}'.format(number))
@dec.deco(txt='kw_argument')
def random(self):
return np.random.rand(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
我希望在调用 self.normal()
时尽可能频繁地获取 'kw_argument' 和 'in decorator' 的打印,但只获取了一次。我做错了什么?
您可以改用函数装饰器:
import time, sys
from functools import wraps
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
def dec2(*args, **kwargs):
def real_decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
print(args, kwargs)
print("In decorator")
return fn(*args, **kwargs)
return wrapper
return real_decorator
class Window(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.thread = Worker()
label = QLabel(self.tr("random number"))
self.thread.output[str].connect(label.setText)
layout = QGridLayout()
layout.addWidget(label, 0, 0)
self.setLayout(layout)
self.thread.start()
class Worker(QThread):
output = pyqtSignal(str)
def run(self):
# Note: This is never called directly. It is called by Qt once the
# thread environment has been set up.
while True:
time.sleep(1)
number = self.random()
self.output.emit('random number {}'.format(number))
@dec2(txt='kw_argument')
def random(self):
return np.random.rand(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
输出:
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
(<__main__.Worker object at 0x10edc37d0>,) {}
In decorator
...
如果您真的需要始终打印 txt,请坚持使用 class 装饰器:
class dec2(object):
def __init__(self, *args, **kwargs):
self.deco_args = args
self.deco_kwargs = kwargs
def __call__(self, f):
def wrapped_f(*args):
print(self.deco_kwargs['txt'])
print('in decorator')
return f(*args)
return wrapped_f
输出:
w_argument
in decorator
kw_argument
in decorator
...