Schreiben von Dekorateur Hinzufügen von Anrufläden, die Objekte vom generischen Typ zur Instanzliste nehmenPython

Python-Programme
Anonymous
 Schreiben von Dekorateur Hinzufügen von Anrufläden, die Objekte vom generischen Typ zur Instanzliste nehmen

Post by Anonymous »

Ich möchte eine benutzerdefinierte Sammlung (FNCOLL) erstellen, die für ein Objekttyp -T spezifisch ist und eine Liste von Anrufleuten enthält, wobei jeweils ein Objekt vom Typ T verwendet wird und einen beliebigen Wert zurückgibt. < /p>

Code: Select all

class FnColl[T]:
def __init__(self, fns: list[Callable[[T], Any]] = []) -> None:
self.fns: list[Callable[[T], Any]] = fns

def add(self, fn: Callable[[T], Any], invert: bool) -> Self:
if invert:
fn = self._invert(fn=fn)
self.fns.append(fn)
return self

@staticmethod
def _invert(fn: Callable[[T], Any]) -> Callable[[T], Any]: ...
< /code>
Diese Klasse soll in spezifischeren Funktionskollektionen weiter unterklassifiziert sein (z. B. eine Reihe von Filtern, die für eine Objektsammlung verwendet werden sollen). < /p>
class Filters[T](FnColl[T]):
def __init__(self, fns: list[Callable[[T], bool]] = []):
super().__init__(fns=fns)

def add(self, fn: Callable[[T], bool], invert: bool) -> Self:
return super().add(fn=fn, invert=invert)
< /code>
Ich habe dann objektspezifische Implementierungen wie die folgenden. Jede Filterfunktion soll auch ein zusätzliches Argument erhalten, wenn das Ergebnis invertiert wird oder nicht, dass ich für jede Filterfunktion nicht explizit definieren möchte. < /P>
class A
x: int
y: str

class AFilter(Filters[A]):
@add_filter
def has_value_for_x(self, obj: A) -> bool: ...

@add_filter
def has_specific_value_for_y(self, obj: A, specific_value: str) -> bool: ...
Hinweis: @add_filter Hier ist nur ein Dummy noch nicht definiert, um zu zeigen, dass ich einen Dekorationsmechanismus erreichen möchte, um eine Reihe von Filtern wie das folgende ohne Wiederholungscode zu erstellen.

Code: Select all

f = AFilter().has_value_for_x(exclude=True).has_specific_value_for_y(specific_value="abc")
< /code>
Ich möchte mit jeder Filterfunktion eine Sammlung von Filtern erstellen, die das Ausschluss < /code> Argument annimmt, ohne explizit zu definieren, und optional zusätzliche Argumente abhängig von der Funktion.class Filters[T](FnColl[T]):
def __init__(self, fns: list[Callable[[T], bool]] = []):
super().__init__(fns=fns)

def add(self, fn: Callable[[T], bool], invert: bool) -> Self:
return super().add(fn=fn, invert=invert)

class Filter[**P, T1: Filters]:
type FilterFn = Callable[Concatenate[T1, T, P], bool]
type FilterApply = Callable[Concatenate[bool, P], T1]

def __init__(self, f: FilterFn) -> None:
self.fn = f

def __call__(
self, _self: T1, exclude: bool = False, *args: P.args, **kwds: P.kwargs
) -> T1:
def f(obj: T) -> bool:
return self.fn(_self, obj, *args, **kwds)

return _self.add(fn=f, invert=exclude)

def __get__(self, instance: T1, owner: type[T1]) -> FilterApply:
return partial(self.__call__, _self=instance)
Bei der Verwendung in Afilter GEGENPRÜFEN T @Filter ist nicht mit einem für Zeile @filters.filter
kompatibel

Code: Select all

class AFilter(Filters[A]):
@Filters.Filter
def has_value_for_x(self, obj: A) -> bool: ...

@Filters.Filter
def has_specific_value_for_y(self, obj: A, specific_value: str) -> bool: ...
< /code>
Wie kann ich einen gültigen Typ -Hinweis /ein Dekorateur definieren, um wiederholten Code zum Hinzufügen der Filterfunktion in die Instanzenliste von Anrufleuten zu vermeiden?class AFilter(Filters[A]):
def has_value_for_x(self, exclude: bool = False) -> Self:
def f(a: A) -> bool:
return a.x is not None

return self.add(fn=f, invert=exclude)

def has_specific_value_for_y(self, specific_value: str, exclude: bool = False) -> Self:
def f(a: A) -> bool:
return a.y == specific_value

return self.add(fn=f, invert=exclude)
< /code>
Für mehrere Filtersammlungen für verschiedene Objekte mit vielen verschiedenen Filterfunktionen, die viel Kesselplatte sind. Unter der Haube ist es immer noch eine einfache Liste von Funktionen, aber [url=viewtopic.php?t=14917]ich möchte[/url] eine standardisierte und definierte Schnittstelle für Filtersammlungen und Hinzufügen von Filtern haben. Trennung der Sammlung und der Dekorateurklasse. Ich habe jedoch keine gegenseitige Abhängigkeit zwischen dem generischen Typ T der Sammlung und dem Filter. Außerdem fehlt mir, in die Argumente der dekorierten Methode (d. H.  Popup in VSCODE zur Anzeige von Methodenargumenten) < /p>
introspektiert zu werden. < /P>
class Filters[T](FnColl[T]):
def __init__(self, fns: list[Callable[[T], bool]] = []):
super().__init__(fns=fns)

def add(self, fn: Callable[[T], bool], invert: bool) -> Self:
return super().add(fn=fn, invert=invert)

class Filter[T, T1: Filters]:
type FilterFn[**P] = Callable[Concatenate[T1, T, P], bool]

def __init__(self, f: FilterFn) -> None:
self.fn = f

def __call__(
self, _self: T1, exclude: bool = False, *args, **kwds
) -> T1:
@wraps(self.fn)
def f(obj: T) -> bool:
return self.fn(_self, obj, *args, **kwds)

return _self.add(fn=f, invert=exclude)

def __get__(self, instance: T1, owner: type[T1]) -> FilterApply:
return partial(self.__call__, _self=instance)
< /code>
Ich muss definieren: < /p>
class AFilter(Filter[A, "AFilters"]): ...

class AFilters(Filters[A]):
@AFilter
def has_value_for_x(self, obj: A) -> bool: ...

@AFilter
def has_specific_value_for_y(self, obj: A, specific_value: str) -> bool: ...

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post