It is pretty easy to implement __len__(self) method in Python so that it handles len(inst) calls like this one:
class A(object):
def __len__(self):
return 7
a = A()
len(a) # gives us 7
And there are plenty of alike methods you can define (__eq__, __str__, __repr__ etc.).
I know that Python classes are objects as well.
My question: can I somehow define, for example, __len__ so that the following works:
len(A) # makes sense and gives some predictable result
What you’re looking for is called a “metaclass”… just like
ais an instance of classA,Ais an instance of class as well, referred to as a metaclass. By default, Python classes are instances of thetypeclass (the only exception is under Python 2, which has some legacy “old style” classes, which are those which don’t inherit fromobject). You can check this by doingtype(A)… it should returntypeitself (yes, that object has been overloaded a little bit).Metaclasses are powerful and brain-twisting enough to deserve more than the quick explanation I was about to write… a good starting point would be this stackoverflow question: What is a Metaclass.
For your particular question, for Python 3, the following creates a metaclass which aliases
len(A)to invoke a class method on A:(Note: Example above is for Python 3. The syntax is slightly different for Python 2: you would use
class A(object):\n __metaclass__=LengthMetaclassinstead of passing it as a parameter.)The reason
LengthMetaclass.__len__doesn’t affect instances ofAis that attribute resolution in Python first checks the instance dict, then walks the class hierarchy[A, object], but it never consults the metaclasses. Whereas accessingA.__len__first consults the instanceA, then walks it’s class hierarchy, which consists of[LengthMetaclass, type].