Rafe Kettler
Rafe Kettler

Reputation: 76965

Preventing a class's function attributes from being passed self as the first arg

Okay, so I've got a class where one of the attributes is a callback function. Problem is, whenever I call it from within the class (e.g. as self.function_attr(), it gets passed self as the first argument. Here's an idea of what I'm working with:

def callback(a, b):
    # do something with a, b

class A:
    def __init__(self, callback):
        self.callback = callback
        self.callback(1, 2) # Raises a TypeError: takes exactly 2 arguments (3 given)

I'm not willing to write each callback function to take self as a first argument. I wrote a decorator that works around the issue:

def callback_decorator(func):
    def newfunc(self, *args, **kw):
        return func(*args, **kw)
    return newfunc

but I'm wondering if there's anything better.

Basically, my question is, how can I call instance attributes of my class which are functions without them being passed self as the first argument?

Upvotes: 1

Views: 136

Answers (2)

agf
agf

Reputation: 176910

You just need to make it a staticmethod when you bind it to the class.

def callback(a, b):
    # do something with a, b

class A:
    def __init__(self, callback):
        # now it won't get passed self
        self.callback = staticmethod(callback)
        self.callback(1, 2)

or

class A:
    def __init__(self, callback):
        self.callback(1, 2)

    # now it won't get passed self
    callback = staticmethod(callback)

Upvotes: 2

detly
detly

Reputation: 30342

As far as I know, a wrapper (like your decorator) is the simplest way to go. Since you already have an object in which to store the function, I wouldn't bother with a decorator. (Note I've inherited from object, which is something you should probably be doing unless you specifically want old-style class behaviour.)

class A(object):

    def __init__(self, callback):
        self._callback = callback
        self.callback(1,2)


    def callback(self, *args, **kwargs):
        return self._callback(*args, **kwargs)

This behaves as you'd expect:

>>> def f(x, y):
...     print "X: %s, Y: %s" % (x,y)
... 
>>> mya = A(f)
X: 1, Y: 2

Upvotes: 0

Related Questions