Reputation: 4644
Suppose you have a function with multiple arguments:
def foo(x1, x2, x3, y):
pass
I am trying to make a class, named FAI
, behave a little like the functools.partial
function.
bar = my_class(foo, 1, 2, 3)
bar("a")
# `bar("a")` supposed to be the same as `foo(1, 2, 3, "a")`
When I run the following code:
def bar(*args):
print(args)
bar = FAI(bar, 1)
bar = FAI(bar, 2)
bar = FAI(bar, 3)
bar = FAI(bar, 4)
bar = FAI(bar, 5)
bar = FAI(bar, 6)
bar("a", "b", "c")
The sys.stdout
output I get is:
(1, 'a', 'b', 'c')
The desired output is one of the following:
(1, 2, 3, 4, 5, 6, 'a', 'b', 'c')
(6, 5, 4, 3, 2, 1, 'a', 'b', 'c')
How do I get the desired output?
import functools
import inspect
class Meta(type):
functools=functools
inspect=inspect
def __call__(self, imp, *args, **kwargs):
"""
instance = Klass(imp)
instance = Klass.__call__(imp)
instance = Meta.__call__(Klass, imp)
"""
# `imp`.......`implementation`
Meta = type(self)
SuperMeta = Meta.inspect.getmro(Meta)[1]
inst = SuperMeta.__call__(self, imp, *args, **kwargs)
inst = functools.update_wrapper(wrapper=inst, wrapped=imp)
return inst # instance
class FAI(metaclass=Meta):
"""
`FAI`..........`First argument inputter`
"""
def __init__(self, imp, arg):
# `imp`.......`implementation`
assert (callable(imp))
self._arg = arg
self._imp = imp
def __call__(self, *args, **kwargs):
return self._imp(self._arg, *args, **kwargs)
Upvotes: 0
Views: 51
Reputation: 280456
You're using functools.update_wrapper
. You shouldn't. It's designed to work with functions of the type defined by def
, not arbitrary callables.
Your update_wrapper
is copying the _arg
and _imp
attributes from old FAI
instances to new ones, so the last one has the first one's _arg
and _imp
.
Also, your Meta.__call__
has the most bizarrely manual implementation of the super(type(self), self)
bug I've seen yet. If you ever create a subclass of Meta
(which can happen without you even noticing, if you don't understand the libraries you use), SuperMeta
will be Meta
itself or some other wrong class. Use super().__call__(imp, *args, **kwargs)
there.
Upvotes: 1