Sie möchten wahrscheinlich eine Metaklasse hier: eine Metaklasse definiert einfach, wie eine Klasse erstellt wird. Standardmäßig werden alle Klassen erstellt Pythons eingebaute Klasse mit type
:
>>> class Foo:
... pass
...
>>> type(Foo)
<class 'type'>
>>> isinstance(Foo, type)
True
So Klassen sind eigentlich Instanzen type
. Jetzt können wir type
Unterklasse eine benutzerdefinierte metaclass (eine Klasse, die Klassen erstellt) zu erstellen:
class PatchMeta(type):
"""A metaclass to patch all inherited classes."""
wir die Schaffung unserer Klassen steuern müssen, so wollen wir die type.__new__
hier außer Kraft gesetzt, und verwenden Sie die patch
Dekorateur auf allen neuen Instanzen:
class PatchMeta(type):
"""A metaclass to patch all inherited classes."""
def __new__(meta, name, bases, attrs):
cls = type.__new__(meta, name, bases, attrs)
cls = patch("some.core.function", mocked_method)(cls)
return cls
Und jetzt stellen Sie einfach die Metaklasse mit __metaclass__ = PatchMeta
:
class BaseTest(unittest.TestCase):
__metaclass__ = PatchMeta
# methods
Das Problem ist, diese Zeile:
cls = patch("some.core.function", mocked_method)(cls)
So derzeit wir immer mit Argumenten dekorieren "some.core.function"
und mocked_method
. Stattdessen könnten Sie machen es so, dass es die Attribute des Klasse verwendet, etwa so:
cls = patch(*cls.patch_args)(cls)
Und dann patch_args
zu Ihren Klassen hinzufügen:
class BaseTest(unittest.TestCase):
__metaclass__ = PatchMeta
patch_args = ("some.core.function", mocked_method)
Edit: Wie @mgilson erwähnt In den Kommentaren ändert patch()
die Methoden der Klasse anstelle einer neuen Klasse.Aus diesem Grund können wir die __new__
mit diesem __init__
ersetzen:
class PatchMeta(type):
"""A metaclass to patch all inherited classes."""
def __init__(cls, *args, **kwargs):
super(PatchMeta, self).__init__(*args, **kwargs)
patch(*cls.patch_args)(cls)
die ganz unarguably sauberer ist.
Dies ist wahrscheinlich, wo Sie google ["Python Metaklassen"] (https://www.google.fi/search?q=python+metaclasses) und lesen Sie weiter, bis Sie verstehen, wie sie funktionieren. Metaklasse wird von den Unterklassen geerbt, Dekoratoren dekorieren nur die Klasse, in der sie verwendet werden. –
Ah, ich glaube ich verstehe was du meinst. Patches treten nur bei Instanzen von Klassen auf? – sihrc
Nein, 'patch' ist ein Dekorateur, der nur die Klasse direkt darunter nimmt und diese verziert. Jetzt werden keine Unterklassen dekoriert, sie werden nur normale Klassen sein. Metaklassen steuern das Verhalten der Klassen und können daher eine Klasse bei ihrer Erstellung patchen. Metaklassen funktionieren auch auf Unterklassen, nachdem die Metaklasse der Basisklasse festgelegt wurde. Daher werden Unterklassen ebenfalls gepatcht. –