1
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

6
  • 2
    Do you not want to use @classmethod on a def to_ghost(...):? Commented May 8, 2015 at 19:54
  • 2
    possible duplicate of What is the difference between a function, an unbound method and a bound method? Commented May 8, 2015 at 20:02
  • 2
    A lambda is no different than any other method definition inside a class body. Unless you mark it as a @staticmethod it will expect a self parameter. Commented May 8, 2015 at 20:08
  • @tzaman: yes for some reason the fact that I assign the method to a class attribute made me think it would itself be a "static" method Commented May 8, 2015 at 20:11
  • lambdas are anonymous functions and assigning them to variables like that is usually bad practice. You loose doc strings and decorators and generally cause others to scratch their heads wondering why you did it. Just use a def for named functions. Commented May 8, 2015 at 20:11

2 Answers 2

5

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
Sign up to request clarification or add additional context in comments.

3 Comments

Yes I guessed so - but it still surprises me - I would expect the lambda to be a static method - how come it is interpreted as a instance method?
@Mr_and_Mrs_D You mean "instancemethod", not "classmethod" -- they're different. And the interpretation depends on how the method is looked up. Read up on the "descriptor protocol".
@tzaman: that's what I would like to see some clarifications on :)
3

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.

1 Comment

Thanks for catching the real question - I had a difficulty phrasing it - now I know how I should refactor :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.