Mr_and_Mrs_D
Mr_and_Mrs_D

Reputation: 34036

Calling lambda method defined in class scope (as a class attribute)

class _GhostLink(object):
    toGhost = lambda filename: False

class _Mod_AllowGhosting_All(_GhostLink):
    def _loop(self):
        # ...
        if self.__class__.toGhost(fileName) != oldGhost:...

produces:

Traceback (most recent call last):
  File "bash\basher\mod_links.py", line 592, in Execute
    changed = self._loop()
  File "bash\basher\mod_links.py", line 587, in _loop
    if self.__class__.toGhost(fileName) != oldGhost:
TypeError: unbound method <lambda>() must be called with _Mod_AllowGhosting_All instance as first argument (got Path instance instead)

while passing an instance as in if self.toGhost(fileName) != ... results in:

Traceback (most recent call last):
  File "bash\basher\mod_links.py", line 592, in Execute
    changed = self._loop()
  File "bash\basher\mod_links.py", line 587, in _loop
    if self.toGhost(fileName) != oldGhost:
TypeError: <lambda>() takes exactly 1 argument (2 given)

How come toGhost behaves as a classmethod instance method ?

EDIT: I know the difference of class,static etc methods - this is a syntactic question

Upvotes: 1

Views: 1417

Answers (2)

SingleNegationElimination
SingleNegationElimination

Reputation: 156248

The reason this happens is fundamentally that lambda and def do the same thing, except that def also assigns a variable, That is, both constructs produce a function.

The binding of a function (whether from lambda or def) into an instance method happens because functions are also descriptors; remember, in every single case:

foo = lambda (...): (...)

is identical to:

def foo(...):
    return (...)

so when you say:

class _GhostLink(object):
    toGhost = lambda filename: False

It's the same as if you had said:

class _GhostLink(object):
    def toGhost(filename): 
        return False

So the moral of the story is that you should probably never use lambda as the right side of an assignment; it's not "better" or even different from using def. All it does is confuse.

Upvotes: 3

Bi Rico
Bi Rico

Reputation: 25833

Looks like you want a static method:

class _GhostLink(object):
    toGhost = staticmethod(lambda filename: False)

or:

class _GhostLink(object):
    @staticmethod
    def toGhost(filename):
        return False

Upvotes: 5

Related Questions