GOOGLE ADS

четверг, 5 мая 2022 г.

Добавить миксин в перечисление python после его создания?

Эта проблема

Предположим, у меня есть перечисление:

from enum import Enum, auto
class Foo(Enum):
DAVE_GROHL = auto()
MR_T = auto()

и я хочу расширить этот класс только с помощью определенных методов (т.е. без новых членов перечисления):

class MixinFoo(Foo):
def catch_phrase(self):
if self is Foo.MR_T:
return "I pity da foo!"
else:
return "There goes my hero!"

Это не удастся с TypeError, так как по дизайну перечисление не может быть расширено после определения членов. Перечисление Python позволяет вам сделать это в другом направлении (то есть: определить миксин без членов и создать подкласс миксина для добавления членов), но в моем конкретном случае использования определение MixinFooперед Fooиспользованием в качестве базового класса не вариант (например: Fooопределен в другом модуле, и я не хочу воссоздавать его или изменять код этого модуля).

Что я рассмотрел до сих пор:

Настройка EnumMeta. EnumMetaпроверяет наличие существующих членов в базовом классе в __prepare__методе, поэтому может сработать переопределение этого метода и отсрочка проверки в новом метаклассе. К сожалению, EnumMetaпроверка существующих членов в нескольких других функциях и переопределение всех этих функций в целом кажутся плохой практикой (много дублированного кода).

Добавление функций постфактум. Я знаю, что можно сделать что-то вроде:

def catch_phrase(self):
...
Foo.catch_phrase = catch_phrase

и хотя это может работать, есть некоторые существенные недостатки, которых я хотел бы избежать (например: очень громоздкий для большого количества функций, статические методы/методы класса, свойства обычного определения класса могут быть трудно реализовать)

Решение проблемы с композицией над наследованием:

class FooWrapper():
def __init__(self, foo):
self._foo = foo
def catch_phrase(self):
...

Хотя это возможно, я не большой поклонник этого метода.

Некоторые связанные вопросы:

Why does EnumMeta have checks for existing members outside of __prepare__? From a design perspective, this seems to not only be redundant, but also makes it unnecessarily difficult to extend the EnumMeta as in my case. I understand the rationale behind not allowing extension of enums with more members, but mixins were obviously considered in the design of the enum library. Was this an oversight in the design of the enum? Was it considered and rejected? Is it intentional for some reason?

Furthermore, one of the checks for existing members is buried in the _EnumDict class, which is not accessible, so I'm not sure what I'm trying to do is possible without recreating a fairly substantial portion of the enum library.

Общее намерение состоит в том, что у меня есть общее перечисление, в котором члены известны и фиксированы, но вариант использования и методы зависят от приложения (т. е. разные приложения, которые используют, Fooбудут иметь разные приветствия и, возможно, другие функции для добавления, но ни одному приложению не потребуется добавить другие Foos).


Решение проблемы

Работает ли Fooдля вас простое назначение метода?

Как вFoo.catch = lambda self=None: print(Foo if self is None else "MR_T" if self is Foo.MR_T else "Ka-bong")

Если нет, то почему? Для всех целей он ведет себя как метод, и "self" заполняется членом "Foo", если метод вызывается из члена.

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...