Я реализую ряд классов в Equinox, чтобы можно было использовать производные по параметрам класса. Большую часть времени пользователь будет создавать экземпляр класса A и использовать функцию fn для генерации некоторых данных, детали которых не важны. Однако в тех случаях, когда нас интересуют градиенты, полезно представить param_c в виде сигмовидной функции, чтобы гарантировать, что он останется зафиксированным в диапазоне (0,1). Однако я не хочу, чтобы пользователь заметил разницу в поведении класса, если он это сделает. Таким образом, я реализую другой класс A_sigmoid, который имеет параметр param_c в качестве свойства, и использую A_abstract, чтобы гарантировать, что оба класса наследуют метод fn, который будет вызывать param_c в его логике. Хотя я мог бы просто попросить пользователя создать экземпляр объекта A_sigmoid с помощью _param_c_sigmoid вместо param_c, я не хочу заставлять пользователя делать это различие. Скорее, я бы хотел, чтобы они передавались в один и тот же словарь kwargs независимо от класса и чтобы преобразование происходило незаметно. Я также хотел сделать так, чтобы при создании нового A можно было просто передать необязательный флаг, чтобы указать программе использовать сигмовидную версию кода. Для этого я реализовал следующий MWE:
class A_abstract(eqx.Module):
param_a: jax.Array
param_b: jax.Array
param_c: eqx.AbstractVar[jax.Array]
def fn(self,*args,**kwargs):
pass
class A_sigmoid(A_abstract):
_param_c_sigmoid: jax.Array
@property
def param_c(self):
return 1 / (1 + jnp.exp(-self._param_c_sigmoid))
class A(A_abstract):
param_c: jax.Array
def __new__(cls, **kwargs):
sigmoid_flag = kwargs.pop('use_sigmoid_c',False)
if sigmoid_flag == True:
param_c = kwargs.pop('param_c')
_param_c_sigmoid = jnp.log(param_c / (1 - param_c))
kwargs['_param_c_sigmoid'] = _param_c_sigmoid
instance = A_sigmoid.__new__(A_sigmoid)
instance.__init__(**kwargs)
print(type(instance))
return instance
else:
return super(A,cls).__new__(cls)
classA = A(param_a = 1.,param_b = 2.,param_c = 0.5,use_sigmoid_c=True)
print(type(classA))
В коде правильно указано, что экземпляр имеет тип A_sigmoid, когда print вызывается в методе __new__. Однако когда я печатаю type(classA), он имеет тип A и не имеет атрибута param_c, хотя у него есть значение для _param_c_sigmoid. Почему это так? Я что-то упустил при использовании __new__, что вызывает эту ошибку? Хотя я знаю, что в принципе лучшим способом сделать это будет фабрика, существуют другие классы типов B, C и т. д., которым не нужна сигмовидная реализация, и которые Я хотел бы вести себя точно так же, как A, чтобы их можно было легко менять местами. Таким образом, я не хочу, чтобы какой-либо собственный метод создавал экземпляр A, который отличался бы от вызова конструктора по умолчанию в других классах.
Я запускаю это в блокноте Jupyter. со следующими версиями пакета:
Python : 3.12.4
IPython : 8.30.0
ipykernel : 6.29.5
jupyter_client : 8.6.3
jupyter_core : 5.7.2
Подробнее здесь: https://stackoverflow.com/questions/793 ... thout-fact
Вернуть другой класс на основе необязательного флага в аргументах без фабрики. ⇐ Python
Программы на Python
1736986628
Anonymous
Я реализую ряд классов в Equinox, чтобы можно было использовать производные по параметрам класса. Большую часть времени пользователь будет создавать экземпляр класса A и использовать функцию fn для генерации некоторых данных, детали которых не важны. Однако в тех случаях, когда нас интересуют градиенты, полезно представить param_c в виде сигмовидной функции, чтобы гарантировать, что он останется зафиксированным в диапазоне (0,1). Однако я не хочу, чтобы пользователь заметил разницу в поведении класса, если он это сделает. Таким образом, я реализую другой класс A_sigmoid, который имеет параметр param_c в качестве свойства, и использую A_abstract, чтобы гарантировать, что оба класса наследуют метод fn, который будет вызывать param_c в его логике. Хотя я мог бы просто попросить пользователя создать экземпляр объекта A_sigmoid с помощью _param_c_sigmoid вместо param_c, я не хочу заставлять пользователя делать это различие. Скорее, я бы хотел, чтобы они передавались в один и тот же словарь kwargs независимо от класса и чтобы преобразование происходило незаметно. Я также хотел сделать так, чтобы при создании нового A можно было просто передать необязательный флаг, чтобы указать программе использовать сигмовидную версию кода. Для этого я реализовал следующий MWE:
class A_abstract(eqx.Module):
param_a: jax.Array
param_b: jax.Array
param_c: eqx.AbstractVar[jax.Array]
def fn(self,*args,**kwargs):
pass
class A_sigmoid(A_abstract):
_param_c_sigmoid: jax.Array
@property
def param_c(self):
return 1 / (1 + jnp.exp(-self._param_c_sigmoid))
class A(A_abstract):
param_c: jax.Array
def __new__(cls, **kwargs):
sigmoid_flag = kwargs.pop('use_sigmoid_c',False)
if sigmoid_flag == True:
param_c = kwargs.pop('param_c')
_param_c_sigmoid = jnp.log(param_c / (1 - param_c))
kwargs['_param_c_sigmoid'] = _param_c_sigmoid
instance = A_sigmoid.__new__(A_sigmoid)
instance.__init__(**kwargs)
print(type(instance))
return instance
else:
return super(A,cls).__new__(cls)
classA = A(param_a = 1.,param_b = 2.,param_c = 0.5,use_sigmoid_c=True)
print(type(classA))
В коде правильно указано, что экземпляр имеет тип A_sigmoid, когда print вызывается в методе __new__. Однако когда я печатаю type(classA), он имеет тип A и не имеет атрибута param_c, хотя у него есть значение для _param_c_sigmoid. Почему это так? Я что-то упустил при использовании __new__, что вызывает эту ошибку? Хотя я знаю, что в принципе лучшим способом сделать это будет фабрика, существуют другие классы типов B, C и т. д., которым не нужна сигмовидная реализация, и которые Я хотел бы вести себя точно так же, как A, чтобы их можно было легко менять местами. Таким образом, я не хочу, чтобы какой-либо собственный метод создавал экземпляр A, который отличался бы от вызова конструктора по умолчанию в других классах.
Я запускаю это в блокноте Jupyter. со следующими версиями пакета:
Python : 3.12.4
IPython : 8.30.0
ipykernel : 6.29.5
jupyter_client : 8.6.3
jupyter_core : 5.7.2
Подробнее здесь: [url]https://stackoverflow.com/questions/79359839/return-a-different-class-based-on-an-optional-flag-in-the-arguments-without-fact[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия