Rufen Sie eine Instanz der Klasse als Dekorator ab, wenn die Klasse/der Dekorator Argumente und weitere Methoden hatPython

Python-Programme
Guest
 Rufen Sie eine Instanz der Klasse als Dekorator ab, wenn die Klasse/der Dekorator Argumente und weitere Methoden hat

Post by Guest »

In Python können Sie Metadaten zu einer Funktion als solcher hinzufügen:

Code: Select all

def test(a,b):
return a+b

test.tags = ["test"]
test.version = "0.1"

print(test.tags) # ['test']
Die Sache ist, dass ich einen Decorator verwende, um meine Funktionen mit einer Orchestrierungsplattform zu protokollieren, die Metadaten unterstützt:

Code: Select all

@orchestrator(
tags = ["test"],
version = "0.1"
)
def test1(a,b):
return a+b
Obwohl es einige Teile der Metadaten gibt, die nicht an den Dekorateur übergeben werden.
Ich wollte eine Klasse erstellen, die mir das Dekorieren ermöglicht eine Funktion, die den Orchestrator-Dekorator und die Metadaten als Methode anwendet (und ich möchte möglicherweise später einige Methoden hinzufügen).
Anfangs habe ich so etwas geschrieben wie:

Code: Select all

class step:

def __init__(self, function, version, description, tags):

self._function    = function
self._version     = version
self._description = description
self._tags        = tags

@orchestrator(
tags = self._tags,
version = self._version
)
def __call__(self):
return self._function

def metadata(self):
return {
"version": self._version,
"description": self._description,
"tags": self._tags,
}

# Other methods...

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
Natürlich hat dieser Ansatz ein paar Probleme:
  • So ist eine Klasse als Dekorator nicht definiert, wenn Sie Argumente an die Klasse übergeben müssen:

    Code: Select all

     # This:
    @step(
    tags = ["test"],
    description = "Example description"
    version = "0.1"
    )
    def test(a,b):
    return a+b
    # Is the same as this:
    step(tags = ["test"], description = "Example description", version = "0.1")(a,b)
    # So step is missing one arguments: function
    
  • Selbst wenn das funktionieren würde, wären self._tags, self._version für den Orchestrator nicht verfügbar Dekorator, wenn sie außerhalb einer Methode liegen.
Mein nächster Versuch war also:

Code: Select all

class step:

def __init__(self, version, description, tags):

self._function    = None
self._version     = version
self._description = description
self._tags        = tags

def __call__(self,):

if not self._function:

@orchestrator(
tags=self._tags,
description=self._description
)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)

self._function = wrapper

return self._function

def metadata(self):
return {
"version": self._version,
"description": self._description,
"tags": self._tags,
}

# Other methods...

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
Dies ist eine Verbesserung, da:
  • Die Funktion dekoriert ist
  • Es wendet den Orchestrator-Dekorator korrekt an
  • Die Funktion wird dekoriert und gespeichert, sodass sie nicht jedes Mal dekoriert wird, wenn ich sie aufrufe
    Aber es erlaubt mir nicht um auf die Methoden zuzugreifen, da test der dekorierte Test und keine Instanz von ist Schritt.
Dadurch kann ich mit print(test.version) usw. auf die Metadaten zugreifen.
Aber ich kann keine Methoden hinzufügen, wie ich es mit test.metadata() versucht habe.
Ich könnte einige der Funktionen umgehen, indem ich Folgendes schreibe:

Code: Select all

class step:

def __init__(self, version, description, tags):

self._function    = None
self._version     = version
self._description = description
self._tags        = tags

def __call__(self,):

if not self._function:

@orchestrator(
tags=self._tags,
description=self._description
)
def wrapper(*args, **kwargs):
return function(*args, **kwargs)

self._function = wrapper
self._function.version = self._version
self._function.description = self._description
self._function.tags = self._tags

return self._function

@step(
tags = ["test"],
description = "Example description"
version = "0.1"
)
def test(a,b):
return a+b
Wie @Jasmijn schrieb, hat dieser letzte Ansatz die gleiche Funktionalität wie:

Code: Select all

def step(tags, description, version):
def _inner(f):
f = orchestrator(tags=tags, version=version)(f)
f.tags = tags
f.description = description
f.version = version
return f
return _inner
Aber dadurch entfällt die Flexibilität, Methoden später hinzuzufügen (beispielsweise test.metadata(), aber möglicherweise sind komplexere Funktionen erforderlich).
Wenn Sie eine Klasse als Dekorator verwenden, der Argumente entgegennimmt, wie kann die Instanz der Klasse in Python anstelle der Methode .__call__() abgerufen werden?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post