LINUX.ORG.RU

Передача функции как аргумента в класс, который запускается как функция.

 


0

4

Как правильно передать функцию как аргумент в класс, который запускается как функция? То есть, как я понял, если вызвать класс в качестве функции, то будет выполнятся метод call.

class FunCall:
    def __init__(self,*args,**kwargs):
        self.__dict__.update(kwargs)
    def __call__(self,p):
        def wrapped(*args, **kwards):
            return p(*args, **kwards)
        return wrapped

def f(x, y, z=10, t=11):
    return x + y + z + t

obj=FunCall(x=1,y=2)
obj.z=2
print obj(f)

Предполагается, что выведется 16=1+2+2+11, тем не менее, выводится <function wrapped at 0x7f006261daa0>. Что посоветуете?

Ответ на: комментарий от baverman

print obj(f)

Это и есть вызов __call__ класса, который выдаёт <function wrapped at 0x7ff90751daa0>, а не значение суммы с учётом переменных экземпляра класса с их приоритетом.

sinhbad
() автор топика
Ответ на: комментарий от sinhbad

Это и есть вызов __call__ класса

Не класса, а инстанса.

который выдаёт <function wrapped at 0x7ff90751daa0>, а не значение суммы

Что возвращаешь, то и выдается.

baverman ★★★
()
Ответ на: комментарий от zz

При:

def __call__(self,p):
        return p(*args, **kwards)
выдаёт ошибку «NameError: global name 'args' is not defined»

Если чуть-чуть подправить:

def __call__(self,p,*args, **kwards):
        return p(args,kwards)
то тоже выдаёт ошибку TypeError: can only concatenate tuple (not «dict») to tuple, что очень странно, т.к. в классе функция вызывается точно так же, как и в основной части программы.

sinhbad
() автор топика
Ответ на: комментарий от sinhbad

да, просто в твоём примере, ты просто вернул функцию warpped, а тебе, как я понял, нужно её вызвать либо в методе __call__ либо в том месте, куда она вернулась.

anonymous
()

Зачем все эти сложности?

class A:
  def __init__(self, a):
    self.a = a
  def foo(self, a):
    print self.a, a

obj = A(1)
foofn = obj.foo
foofn(2)
tailgunner ★★★★★
()

Что посоветуете?

Заменить

print obj(f)

на

print obj(f)()

Попытаться понять.

Не писать больше «Предполагается...», пока не выучишь пайтон.

Да, если не можешь понять поток выполнения программы, добавь несколько инструкций print в точках ветвления алгоритма.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)
Ответ на: комментарий от baverman

partial (и обычная lambda) хорошо работают в простых случаях. А когда параметров, от которых зависит функция, много, лучше делать именно класс. Бонусом идет то, что несколько «функций» могут использовать общие параметры.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)

А на каком языке вы писали ДО питона?

menangen ★★★★★
()
Ответ на: комментарий от tailgunner

А когда параметров, от которых зависит функция, много, лучше делать именно класс.

но это же плохо, когда параметров много

Бонусом идет то, что несколько «функций» могут использовать общие параметры.

для этого есть глобальные переменные ^^

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

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

но это же плохо, когда параметров много

Поэтому делается класс %)

глобальные переменные

Толсто :)

tailgunner ★★★★★
()
Ответ на: комментарий от baverman

Один чай на то, что это лаба по программированию.

tailgunner ★★★★★
()
from functools import partial

def f(x, y, z, t):
    return x + y + z + t

f_z10_t11 = partial(f, z=10, t=11)
f_x1_y2_z10_t11 = partial(f_z10_t11, x=1, y=2)
print(f_x1_y2_z10_t11(z=2))
ei-grad ★★★★★
()

Всем спасибо, появилось решение:

class FunCall(object):
    def __init__(s,*args,**kwargs):
        s.a=args
        s.k=kwargs
    def __call__(s,f):
        return f(*s.a,**s.k)

def f(x, y, z=10, t=11):
    return x + y + z + t

fc = FunCall(1, 2, z=3)
print fc(f)

sinhbad
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.