Существует один способ решить эту проблему, который не был упомянут в сообщении без использования functools
, staticmethod
или функции-оболочки.
Проблема использования определения функции в качестве единственного значения члена Enum заключается в том, что Enum __init__
и __new__
никогда не вызываются. Имея дополнительные значения, Enum инициализируется как обычно.
Доказательство выглядит следующим образом:
import math
from enum import Enum
def relu(x: float) -> float:
return x * (x > 0)
def sigmoid(x: float) -> float:
return 1 / (1 + math.exp(-x))
class Activation(Enum):
SIGMOID = 1, sigmoid
RELU = 2, relu
def __init__(self, *args):
self.your_func = args[1]
def __call__(self, x):
return self.your_func(x)
@classmethod
def values(cls):
return [member.your_func for member in cls]
print(Activation.SIGMOID(2))
print(Activation.RELU(2))
# 0.8807970779778823
# 2
for one_func in Activation.values():
print(one_func(2))
# 0.8807970779778823
# 2
Я не думаю, что это ошибка (как предлагается в комментариях), потому что:
Однако проблема с функциями заключается в том, что они считаются определениями методов вместо атрибутов
Что общего у нескольких решений, так это инкапсуляция определения функции во время перечисления ( синтаксис класса) объявление значения.
Из-за вышеизложенного использование «функции-обертки» без staticmethod
или functools
не будет работать, потому что никогда не будет вызываться. Попробуйте заменить следующее (не будет вызван ни __init__
, ни __call__
):
SIGMOID = sigmoid
RELU = relu
def __call__(self, *args, **kwargs):
print("inside")
return self.f(*args, **kwargs)
В заключение, , возможно, самый подход pythoni c заключает в себе определение функции в список при объявлении и развертывание в __init__
при инициализации:
import math
from enum import Enum
def relu(x: float) -> float:
return x * (x > 0)
def sigmoid(x: float) -> float:
return 1 / (1 + math.exp(-x))
class Activation(Enum):
SIGMOID = [sigmoid]
RELU = [relu]
def __init__(self, your_func):
self.your_func = your_func[0]
def __call__(self, x):
return self.your_func(x)
@classmethod
def values(cls):
return [member.your_func for member in cls]
print(Activation.SIGMOID(2))
print(Activation.RELU(2))
# 0.8807970779778823
# 2
for one_func in Activation.values():
print(one_func(2))
# 0.8807970779778823
# 2
, который сохраняет вызов staticmethod
(некоторые считают его использование unpythoni c вне определения класса). И сохраняет импорт и вызов functools.partial
- это включает ненужные издержки вызова функции при каждом доступе члена.
Таким образом, вышеприведенный подход, возможно, может быть наиболее pythoni c решением.