self
muss ein Positions Argument sein, kein Schlüsselwort Argument:
def wrapper(self, *args, **kwargs):
# ^^^^ You can't use "self=None" here.
slot_func(self, *args, **kwargs)
Wenn Sie zwischen Funktionen und Methoden unterscheiden müssen, implementieren eine descriptor statt.
Wenn Sie jedoch versuchen, ein Signal zu verbinden, müssen Sie eine gebundene Methode für jede Instanz . Sie würden besser Ihre Signale bei Beispiel Erstellungszeit verbindet:
class manager(object):
def __init__(self):
update.connect(self.update)
def update(self):
print("I'm updating, yay!!!!")
Wenn manager.__init__
genannt wird, haben Sie eine neue Instanz haben, und es ist, dann können Sie einself.update
gebundene Methode erstellen die erhalten Signal.
Sie können immer noch Decorator dafür verwenden, aber Sie können am besten auf Klassenebene registrieren, welche Funktionen als Signalhandler fungieren können; Sie müssten alle Funktionen auf Ihrer Klasse bei instanzErstellungsZeit aufzuzählen und binden alle diese Signale dann:
class connector(object):
def __init__(self, signal):
self.signal = signal
def __call__(self, slot_func):
slot_func._signal_handler = self.signal
return slot_func
und eine separate Klasse Dekorateur die class.__init__
Methode wickeln:
from inspect import getmembers, isfunction
def connectsignals(cls):
signal_handlers = getmembers(
cls, lambda m: isfunction(m) and hasattr(m, '_signal_handler'))
init = getattr(cls, '__init__', lambda self: None)
def wrapper(self, *args, **kwargs):
init(self, *args, **kwargs)
for name, handler in signal_handlers:
handler._signal_handler.connect(handler.__get__(self))
cls.__init__ = wrapper
return cls
Verzieren der Klasse sowie die Signal-Handler:
@connectsignals
class manager(object):
@connector(update)
def update(self):
print("I'm updating, yay!!!!")
Der Dekorateur dann alle Handler verbindet jedes Mal, wenn eine neue Instanz erstellt:
>>> class Signal(object):
... def connect(self, handler):
... print('connecting {!r}'.format(handler))
...
>>> update = Signal()
>>> @connectsignals
... class manager(object):
... @connector(update)
... def update(self):
... print("I'm updating, yay!!!!")
...
>>> manager()
connecting <bound method manager.update of <__main__.manager object at 0x105439ac8>>
<__main__.manager object at 0x105439ac8>
Möglicherweise mögen Sie überprüfen, ob das signalslot
Projekt schwachen Verweis verwendet Signal-Handler jedoch zu verfolgen, wie Sie entweder ein Problem des Kreis Verweise auf alle Instanzen, die Sie erstellt haben werden (wo eine manager
Instanz gehalten wird lebendig, weil ein Signal verweist immer noch auf eine gebundene Methode zu dieser Instanz), oder wo Ihre Signalhandler zu früh bereinigt werden, weil Ihre gebundenen Methoden in schwachen Referenzen gespeichert sind und daher keine anderen Referenzen haben, um sie am Leben zu halten.
Mit Blick auf die signalslot
source code, sehe ich, dass die aktuelle Iteration des Projekts verwendet harte Referenzen, so dass Ihre manager
Instanzen werden nie gelöscht werden, wenn Sie dies explizit tun. Aus diesem Grund würde ich es vermeiden, Methoden als Signalhandler zu verwenden. Werfen Sie einen Blick auf using python WeakSet to enable a callback functionality, wenn Sie stattdessen schwache Referenzen verwenden möchten.