user1950164
user1950164

Reputation:

Why doesn't this python assignment work as obviously expected?

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?

Upvotes: 2

Views: 65

Answers (2)

mattjegan
mattjegan

Reputation: 2884

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()

Upvotes: 4

Jacques Gaudin
Jacques Gaudin

Reputation: 16958

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.

Upvotes: 1

Related Questions