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: ...
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)
kompatibelclass 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 ich möchte eine standardisierte und definierte Schnittstelle für Filtersammlungen und Hinzufügen von Filtern haben.>