Как сделать так, чтобы существующие функции в модуле math и numpy поддерживали определяемые пользователем объекты?
Я определил класс, который я хотел бы основные операции, такие как +
, -
и даже более сложные математические операции, такие как sin
поддерживать. То есть мне нужно определить некоторые новые правила для этих основных операторов и математических функций.
Я мог бы иметь дело с базовыми операторами, используя магические методы Python, как показано ниже,
class NewObj():
def __init__(self, *args):
pass
def __add__(self, other):
pass
def __mul__(self, other):
pass
# Use magic methods to define other basic operators below...
И я мог бы также переопределить основные функции в том же файле.py, где класс NewObj
определяется, например,
def sin(x):
pass
И назовите этот файл, скажем, myoperator.py. Тогда я мог бы импортировать этот модуль и применить новые операции на NewObj
объекты.
Но я также хочу существующие функции в numpy
а также math
поддержать мой NewObj
объекты, так что math.sin()
а также numpy.sin()
также поддержать мой недавно определенный NewObj
объекты. Как мне этого добиться?
Другой вопрос: возможно ли инкапсулировать функции внутри моего NewObj
класс так же, как магические методы, так что все вещи написаны внутри структуры данных класса?
3 ответа
math
Модуль явно документы, которые функционируют как math.sin
всегда возвращайте поплавки. Если ты хочешь math.sin(your_object)
вернуть NewObj
экземпляр вместо float
не делай этого. Это может запутать всех, даже если вы заставите это работать, и это вызовет ошибки порядка инициализации и другие головные боли. (Есть причина, по которой у NumPy есть свои numpy.sin
вместо того, чтобы пытаться сделать math.sin
поддержка массивов NumPy.)
Если ты в порядке с math.sin(your_object)
вернуть поплавок, затем реализовать __float__
метод для преобразования ваших объектов в поплавки:
class NewObj(object):
...
def __float__(self):
return whatever
math.sin
преобразует ваш объект в число с плавающей точкой, вычисляет синус числа с плавающей точкой и возвращает синус как число с плавающей точкой.
Для NumPy просто внедрите sin
метод:
class NewObj(object):
...
def sin(self):
return whatever
numpy.sin
будет делегировать вашему sin
метод. Вы можете вернуть NewObj
; нет необходимости бросать, чтобы плавать или что-нибудь. Большинство похожих функций NumPy делегируют методы аналогичным образом. Тем не менее, попытка использовать пользовательские объекты внутри массивов NumPy сводит на нет большинство преимуществ эффективности NumPy, поэтому вы можете пересмотреть свой дизайн, если хотите это сделать.
Вы можете переопределить math
модуля sin
,
import math
class NewObj:
pass
old_sin = math.sin
def new_sin(number):
return 42.0 if isinstance(number, NewObj) else old_sin(number)
math.sin = new_sin
Предположительно вы замените 42.0
с еще более полезным определением.
Будем надеяться, что в не столь отдаленном будущем __numpy_ufunc__
специальный атрибут (имя может быть изменено). Вот соответствующий бит из версии dev от numy docs
class.__numpy_ufunc__(ufunc, method, i, inputs, **kwargs)
Новое в версии 1.11.
Любой класс (подкласс ndarray или нет) может определить этот метод, чтобы переопределить поведение ufuncs NumPy.
[акцент мой]