6

I would like to have some lambda functions available to all instances of one class. Therefore, my idea was to declare the lambda function as class attribute. In the following simplistic code, why can't I evaluate the following lambda function f that I have defined as a class attribute?

In [1]: class MyClass():
   ...:     f = lambda x : 2 * x + 1
   ...:     def __init__(self):
   ...:         pass

In [2]: Inst = MyClass()

In [3]: MyClass.f
Out[3]: <unbound method MyClass.<lambda>>

In [4]: MyClass.f(2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-5fc154bfb75c> in <module>()
----> 1 MyClass.f(2)

TypeError: unbound method <lambda>() must be called with MyClass instance as first argument (got int instance instead)

In [5]: Inst.f(3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-90cde1a87da4> in <module>()
----> 1 Inst.f(3)

TypeError: <lambda>() takes exactly 1 argument (2 given)
pppery
  • 3,731
  • 22
  • 33
  • 46
MarcoMag
  • 556
  • 7
  • 18
  • Interestingly, this code works just fine in 3.X. I wonder what changed between versions? – Kevin Mar 03 '17 at 16:21
  • 1
    FWIW, lambda is for creating anonymous functions; binding a lambda to a name is generally considered to be bad style. – PM 2Ring Mar 03 '17 at 16:22
  • @Kevin Unbound methods are gone in Python 3, see also: https://www.python.org/download/releases/3.0/whatsnew/ . As such, `MyClass.f` is just a regular `function` and the above code doesn't throw. This question is specific to Python 2. – Alex Povel Jun 10 '22 at 13:23
  • You shouldn't be using lambda expressions here... – juanpa.arrivillaga Jun 11 '22 at 19:51

1 Answers1

11

It's as if you wrote the following:

class MyClass():
    def f(x):
        return 2 * x + 1

    def __init__(self):
        pass

The first parameter is named self by convention, so even if you didn't name it self, your function is an instance method whose first parameter is the current instance of MyClass.

You need to make your function a static method instead:

In [1]: %paste
    class MyClass():
        f = staticmethod(lambda x: 2 * x + 1)

        def __init__(self):
            pass

## -- End pasted text --

In [2]: MyClass.f(2)
Out[2]: 5
Blender
  • 289,723
  • 53
  • 439
  • 496