произведение двух функций - PullRequest
2 голосов
/ 25 января 2012

У меня есть две функции, f и g.Оба имеют одинаковую подпись: (x).Я хочу создать новую функцию, z, с такой же подписью:

def z(x):
  return f(x) * g(x)

, за исключением того, что я хотел бы иметь возможность писать

z = f * g вместо вышеуказанногокод.Возможно ли это?

Ответы [ 3 ]

9 голосов
/ 25 января 2012

Что-то близкое возможно возможно:

z = lambda x: f(x) * g(x)

Лично я считаю этот способ более интуитивным, чем z = f * g, потому что математически умножение функций ничего не значит.В зависимости от интерпретации оператора * это может означать состав , то есть z(x) = f(g(x)), но определенно не умножение результатов вызова.С другой стороны, вышеприведенное lambda является очень явным, и, откровенно говоря, для его написания требуется чуть больше символов.


Обновление: Престижность JBernardo для совместной работы.Я думал, что это будет гораздо более хакерским, чем оказалось.Тем не менее, Я бы не советовал использовать это в реальном коде.

7 голосов
/ 25 января 2012

Самое смешное, что это вполне возможно.Несколько дней назад я создал проект для таких вещей.

Вот он: FuncBuilder

К настоящему времени вы можете определять только переменные, но вы можете использовать мой метаклассс помощью некоторых других функций построить класс по вашему желанию.

Проблемы:

  • Это медленно
  • Это действительно медленно
  • Вы думаете, что хотите этого, но правильное описание функций - это то, что они хотели описать.

Вы должны использовать свой первый код.

Просто как подтверждение концепции:

from funcbuilder import OperatorMachinery

class FuncOperations(metaclass=OperatorMachinery):
     def __init__(self, function):
          self.func = function
     def __call__(self, *args, **kwargs):
          return self.func(*args, **kwargs)

def func(self, *n, oper=None):
    if not n:
        return type(self)(lambda x: oper(self.func(x)))
    return type(self)(lambda x: oper(self.func(x), n[0](x)))

FuncOperations.apply_operators([func, func])

Теперь вы можете кодировать так:

@FuncOperations
def f(x):
    return x + 1

@FuncOperations
def g(x):
    return x + 2

И желаемое поведение:

>>> z = f * g
>>> z(3)
20

Я добавил лучшую версию этогопроект FuncBuilder .Он работает с любой операцией между объектом FuncOperation и другим вызываемым объектом.Также работает на одинарных операциях.: D

Вы можете играть с ним, чтобы сделать такие функции, как:

z = -f + g * h
3 голосов
/ 25 января 2012

Я могу сделать с точным синтаксисом, который вы намеревались (хотя использование лямбда может быть лучше), используя декоратор.Как уже говорилось, для функций не определены операторы, но объекты можно сделать так, чтобы их можно было вызывать так же, как и функции в Python. Поэтому декоратор ниже просто оборачивает функцию в объект, для которого определено умножение для другой функции:

class multipliable(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kw):
        return self.func(*args, **kw)
    def __mul__(self, other):
        @multipliable
        def new_func(*args, **kw):
            return self.func(*args, **kw) * other(*args, **kw)
        return new_func

@multipliable
def x():
    return 2

(протестировано в Python 2 и Python 3)

def y():
    return 3

z = x * y
z()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...