2

This returns what you'd expect:

class My(object):
    def __len__(self):
        return 6

a = My()
print(len(a))

But this throws an error:

class My2(object):
    pass

b = My2()
b.__len__ = lambda x: 6
print(len(b))

TypeError: object of type 'My2' has no len()

Why?

2
  • @DanFarrell "Because a lambda isn't a function?" Is that a question or a statement? Commented Dec 20, 2017 at 23:54
  • @DanFarrell Lambdas are functions, as you can check from callable(lambda x: x) returning True. And next time maybe you'll want to avoid ending your statements with question marks. Commented Dec 21, 2017 at 0:24

2 Answers 2

4

It is because you are trying to define the method on the instance not on the underlying class. For example, this would work:

class My2(object):
    pass

b = My2()
b.__class__.__len__ = lambda x: 6
print(len(b))  # Prints 6

Furthermore to clarify the comments, it is not a matter of it being a lambda or a function as proven by this not working:

class My2(object):
    pass


def l(x):
    return 6

b = My2()
b.__len__ = l
print(len(b))  # TypeError: object of type 'My2' has no len()
Sign up to request clarification or add additional context in comments.

2 Comments

There is a typo in the first code block: b.__class__.__len__ = lambda x: 6
Thanks @JacquesGaudin I've fixed the answer.
1

In Python len(a) as other "magic" functions, is a shorthand for type(a).__len__(a).

Therefore the function (as opposed to method) __len__ you define on the instance b cannot be accessed through len since the call would be resolved as:

type(b).__len__(b)

But type(b) doesn't have a method __len__.

I asked a similar question and got a very good answer here

The documentation is worth reading. Your example is almost identical.

Comments

Your Answer

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